diff --git a/package.json b/package.json
index b18bced..0020771 100644
--- a/package.json
+++ b/package.json
@@ -7,7 +7,9 @@
},
"devDependencies": {
"@types/bun": "latest",
- "@types/node": "^20.12.7"
+ "@types/node": "^20.12.7",
+ "@types/stylus": "^0.48.42",
+ "stylus": "^0.63.0"
},
"peerDependencies": {
"typescript": "^5.0.0"
diff --git a/src/assets/css/button.styl b/src/assets/css/button.styl
new file mode 100644
index 0000000..43a79de
--- /dev/null
+++ b/src/assets/css/button.styl
@@ -0,0 +1,108 @@
+.bx-button {
+ background-color: var(--bx-default-button-color);
+ user-select: none;
+ -webkit-user-select: none;
+ color: #fff;
+ font-family: var(--bx-title-font-semibold);
+ font-size: 14px;
+ border: none;
+ font-weight: 400;
+ height: var(--bx-button-height);
+ border-radius: 4px;
+ padding: 0 8px;
+ text-transform: uppercase;
+ cursor: pointer;
+ overflow: hidden;
+
+ &:focus {
+ outline: none !important;
+ }
+
+ &:hover, &.bx-focusable:focus {
+ background-color: var(--bx-default-button-hover-color);
+ }
+
+ &:disabled {
+ cursor: default;
+ background-color: var(--bx-default-button-disabled-color);
+ }
+
+ &.bx-ghost {
+ background-color: transparent;
+
+ &:hover, &.bx-focusable:focus {
+ background-color: var(--bx-default-button-hover-color);
+ }
+ }
+
+ &.bx-primary {
+ background-color: var(--bx-primary-button-color);
+
+ &:hover, &.bx-focusable:focus {
+ background-color: var(--bx-primary-button-hover-color);
+ }
+
+ &:disabled {
+ background-color: var(--bx-primary-button-disabled-color);
+ }
+ }
+
+ &.bx-danger {
+ background-color: var(--bx-danger-button-color);
+
+ &:hover, &.bx-focusable:focus {
+ background-color: var(--bx-danger-button-hover-color);
+ }
+
+ &:disabled {
+ background-color: var(--bx-danger-button-disabled-color);
+ }
+ }
+
+ svg {
+ display: inline-block;
+ width: 16px;
+ height: var(--bx-button-height);
+
+ &:not(:only-child) {
+ margin-right: 4px;
+ }
+ }
+
+ span {
+ display: inline-block;
+ height: calc(var(--bx-button-height) - 2px);
+ line-height: var(--bx-button-height);
+ vertical-align: middle;
+ color: #fff;
+ overflow: hidden;
+ white-space: nowrap;
+ }
+
+ &.bx-focusable {
+ position: relative;
+
+ &::after {
+ border: 2px solid transparent;
+ border-radius: 4px;
+ }
+
+ &:focus::after {
+ content: '';
+ border-color: white;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ }
+ }
+}
+
+a.bx-button {
+ display: inline-block;
+
+ &.bx-full-width {
+ text-align: center;
+ }
+}
diff --git a/src/assets/css/dialog.styl b/src/assets/css/dialog.styl
new file mode 100644
index 0000000..381988b
--- /dev/null
+++ b/src/assets/css/dialog.styl
@@ -0,0 +1,95 @@
+.bx-dialog-overlay {
+ position: fixed;
+ inset: 0;
+ z-index: var(--bx-dialog-overlay-z-index);
+ background: black;
+ opacity: 50%;
+}
+
+.bx-dialog {
+ display: flex;
+ flex-flow: column;
+ max-height: 90vh;
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ margin-right: -50%;
+ transform: translate(-50%, -50%);
+ min-width: 420px;
+ padding: 20px;
+ border-radius: 8px;
+ z-index: var(--bx-dialog-z-index);
+ background: #1a1b1e;
+ color: #fff;
+ font-weight: 400;
+ font-size: 16px;
+ font-family: var(--bx-normal-font);
+ box-shadow: 0 0 6px #000;
+ user-select: none;
+ -webkit-user-select: none;
+
+ *:focus {
+ outline: none !important;
+ }
+
+ h2 {
+ display: flex;
+ margin-bottom: 12px;
+
+ b {
+ flex: 1;
+ color: #fff;
+ display: block;
+ font-family: var(--bx-title-font);
+ font-size: 26px;
+ font-weight: 400;
+ line-height: var(--bx-button-height);
+ }
+ }
+
+ &.bx-binding-dialog {
+ h2 {
+ b {
+ font-family: var(--bx-promptfont-font) !important;
+ }
+ }
+ }
+
+ > div {
+ overflow: auto;
+ padding: 2px 0;
+ }
+
+ > button {
+ padding: 8px 32px;
+ margin: 10px auto 0;
+ border: none;
+ border-radius: 4px;
+ display: block;
+ background-color: #2d3036;
+ text-align: center;
+ color: white;
+ text-transform: uppercase;
+ font-family: var(--bx-title-font);
+ font-weight: 400;
+ line-height: 18px;
+ font-size: 14px;
+
+ &:hover {
+ @media (hover: hover) {
+ background-color: #515863;
+ }
+ }
+
+ &:focus {
+ background-color: #515863;
+ }
+ }
+}
+
+
+@media screen and (max-width: 450px) {
+ .bx-dialog {
+ min-width: 100%;
+ }
+}
diff --git a/src/assets/css/global-settings.styl b/src/assets/css/global-settings.styl
new file mode 100644
index 0000000..dc040de
--- /dev/null
+++ b/src/assets/css/global-settings.styl
@@ -0,0 +1,169 @@
+.bx-settings-reload-button-wrapper {
+ z-index: var(--bx-reload-button-z-index);
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center;
+ background: #000000cf;
+ padding: 10px;
+
+ button {
+ max-width: 450px;
+ margin: 0 !important;
+ }
+}
+
+.bx-settings-container {
+ background-color: #151515;
+ user-select: none;
+ -webkit-user-select: none;
+ color: #fff;
+ font-family: var(--bx-normal-font);
+}
+
+@media (hover: hover) {
+ .bx-settings-wrapper a.bx-settings-title:hover {
+ color: #83f73a;
+ }
+}
+
+.bx-settings-wrapper {
+ width: 450px;
+ margin: auto;
+ padding: 12px 6px;
+
+ @media screen and (max-width: 450px) {
+ width: 100%;
+ }
+
+ *:focus {
+ outline: none !important;
+ }
+
+ .bx-settings-title-wrapper {
+ display: flex;
+ margin-bottom: 10px;
+ align-items: center;
+ }
+
+ a.bx-settings-title {
+ font-family: var(--bx-title-font);
+ font-size: 1.4rem;
+ text-decoration: none;
+ font-weight: bold;
+ display: block;
+ color: #5dc21e;
+ flex: 1;
+
+ &:focus {
+ color: #83f73a;
+ }
+ }
+
+ .bx-button.bx-primary {
+ margin-top: 8px;
+ }
+
+ a.bx-settings-update {
+ display: block;
+ color: #ff834b;
+ text-decoration: none;
+ margin-bottom: 8px;
+ text-align: center;
+ background: #222;
+ border-radius: 4px;
+ padding: 4px;
+
+ &:hover {
+ @media (hover: hover) {
+ color: #ff9869;
+ text-decoration: underline;
+ }
+ }
+
+ &:focus {
+ color: #ff9869;
+ text-decoration: underline;
+ }
+ }
+}
+
+.bx-settings-group-label {
+ font-weight: bold;
+ display: block;
+ font-size: 1.1rem;
+}
+
+
+.bx-settings-row {
+ display: flex;
+ margin-bottom: 8px;
+ padding: 2px 4px;
+
+ label {
+ flex: 1;
+ align-self: center;
+ margin-bottom: 0;
+ padding-left: 10px;
+ }
+
+
+ &:focus-within {
+ @media (hover: none) {
+ background-color: #242424;
+ }
+ }
+
+ input {
+ align-self: center;
+ accent-color: var(--bx-primary-button-color);
+ }
+
+ select:disabled {
+ -webkit-appearance: none;
+ background: transparent;
+ text-align-last: right;
+ border: none;
+ color: #fff;
+ }
+}
+
+.bx-settings-group-label b, .bx-settings-row label b {
+ display: block;
+ font-size: 12px;
+ font-style: italic;
+ font-weight: normal;
+ color: #828282;
+}
+
+.bx-settings-group-label b {
+ margin-bottom: 8px;
+}
+
+.bx-settings-app-version {
+ margin-top: 10px;
+ text-align: center;
+ color: #747474;
+ font-size: 12px;
+}
+
+.bx-donation-link {
+ display: block;
+ text-align: center;
+ text-decoration: none;
+ height: 20px;
+ line-height: 20px;
+ font-size: 14px;
+ margin-top: 10px;
+ color: #5dc21e;
+
+ &:hover {
+ color: #6dd72b;
+ }
+}
+
+.bx-settings-custom-user-agent {
+ display: block;
+ width: 100%;
+}
diff --git a/src/assets/css/header.styl b/src/assets/css/header.styl
new file mode 100644
index 0000000..ad08266
--- /dev/null
+++ b/src/assets/css/header.styl
@@ -0,0 +1,23 @@
+.bx-header-remote-play-button {
+ height: auto;
+ margin-right: 8px !important;
+
+ svg {
+ width: 24px;
+ height: 46px;
+ }
+}
+
+.bx-header-settings-button {
+ line-height: 30px;
+ font-size: 14px;
+ text-transform: uppercase;
+ position: relative;
+
+ &[data-update-available]::before {
+ content: '🌟' !important;
+ line-height: var(--bx-button-height);
+ display: inline-block;
+ margin-left: 4px;
+ }
+}
diff --git a/src/assets/css/loading-screen.styl b/src/assets/css/loading-screen.styl
new file mode 100644
index 0000000..90da19d
--- /dev/null
+++ b/src/assets/css/loading-screen.styl
@@ -0,0 +1,31 @@
+.bx-wait-time-box {
+ position: fixed;
+ top: 0;
+ right: 0;
+ background-color: #000000cc;
+ color: #fff;
+ z-index: var(--bx-wait-time-box-z-index);
+ padding: 12px;
+ border-radius: 0 0 0 8px;
+
+ label {
+ display: block;
+ text-transform: uppercase;
+ text-align: right;
+ font-size: 12px;
+ font-weight: bold;
+ margin: 0;
+ }
+
+ span {
+ display: block;
+ font-family: var(--bx-monospaced-font);
+ text-align: right;
+ font-size: 16px;
+ margin-bottom: 10px;
+
+ &:last-of-type {
+ margin-bottom: 0;
+ }
+ }
+}
diff --git a/src/assets/css/mkb.styl b/src/assets/css/mkb.styl
new file mode 100644
index 0000000..4ab0b25
--- /dev/null
+++ b/src/assets/css/mkb.styl
@@ -0,0 +1,166 @@
+.bx-mkb-settings {
+ display: flex;
+ flex-direction: column;
+ flex: 1;
+ padding-bottom: 10px;
+ overflow: hidden;
+
+ select:disabled {
+ -webkit-appearance: none;
+ background: transparent;
+ text-align-last: right;
+ text-align: right;
+ border: none;
+ color: #fff;
+ }
+}
+
+.bx-mkb-pointer-lock-msg {
+ display: flex;
+ cursor: pointer;
+ user-select: none;
+ -webkit-user-select: none;
+ position: fixed;
+ left: 50%;
+ top: 50%;
+ transform: translateX(-50%) translateY(-50%);
+ margin: auto;
+ background: #000000e5;
+ z-index: var(--bx-mkb-pointer-lock-msg-z-index);
+ color: #fff;
+ text-align: center;
+ font-weight: 400;
+ font-family: "Segoe UI", Arial, Helvetica, sans-serif;
+ font-size: 1.3rem;
+ padding: 12px;
+ border-radius: 8px;
+ align-items: center;
+ box-shadow: 0 0 6px #000;
+
+ &:hover {
+ background: #151515;
+ }
+
+ button {
+ margin-right: 12px;
+ height: 60px;
+ }
+
+ svg {
+ width: 32px;
+ }
+
+ div {
+ display: flex;
+ flex-direction: column;
+ text-align: left;
+ }
+
+ p {
+ margin: 0;
+
+ &:first-child {
+ font-size: 22px;
+ margin-bottom: 8px;
+ }
+
+ &:last-child {
+ font-size: 14px;
+ font-style: italic;
+ }
+ }
+}
+
+.bx-mkb-preset-tools {
+ display: flex;
+ margin-bottom: 12px;
+
+ select {
+ flex: 1;
+ }
+
+ button {
+ margin-left: 6px;
+ }
+}
+
+
+.bx-mkb-settings-rows {
+ flex: 1;
+ overflow: scroll;
+}
+
+.bx-mkb-key-row {
+ display: flex;
+ margin-bottom: 10px;
+ align-items: center;
+
+
+ label {
+ margin-bottom: 0;
+ font-family: var(--bx-promptfont-font);
+ font-size: 26px;
+ text-align: center;
+ width: 26px;
+ height: 32px;
+ line-height: 32px;
+ }
+
+ button {
+ flex: 1;
+ height: 32px;
+ line-height: 32px;
+ margin: 0 0 0 10px;
+ background: transparent;
+ border: none;
+ color: white;
+ border-radius: 0;
+ border-left: 1px solid #373737;
+
+ &:hover {
+ background: transparent;
+ cursor: default;
+ }
+ }
+}
+
+
+.bx-mkb-settings.bx-editing .bx-mkb-key-row button {
+ background: #393939;
+ border-radius: 4px;
+ border: none;
+
+ &:hover {
+ background: #333;
+ cursor: pointer;
+ }
+}
+
+.bx-mkb-action-buttons {
+ > div {
+ text-align: right;
+ display: none;
+ }
+
+ button {
+ margin-left: 8px;
+ }
+}
+
+.bx-mkb-settings:not(.bx-editing) .bx-mkb-action-buttons > div:first-child {
+ display: block;
+}
+
+.bx-mkb-settings.bx-editing .bx-mkb-action-buttons > div:last-child {
+ display: block;
+}
+
+.bx-mkb-note {
+ display: block;
+ margin: 16px 0 10px;
+ font-size: 12px;
+
+ &:first-of-type {
+ margin-top: 0;
+ }
+}
diff --git a/src/assets/css/number-stepper.styl b/src/assets/css/number-stepper.styl
new file mode 100644
index 0000000..d6759b4
--- /dev/null
+++ b/src/assets/css/number-stepper.styl
@@ -0,0 +1,41 @@
+.bx-number-stepper {
+ span {
+ display: inline-block;
+ width: 40px;
+ font-family: var(--bx-monospaced-font);
+ font-size: 14px;
+ }
+
+ button {
+ border: none;
+ width: 24px;
+ height: 24px;
+ margin: 0 4px;
+ line-height: 24px;
+ background-color: var(--bx-default-button-color);
+ color: #fff;
+ border-radius: 4px;
+ font-weight: bold;
+ font-size: 14px;
+ font-family: var(--bx-monospaced-font);
+ color: #fff;
+
+ &:hover {
+ @media (hover: hover) {
+ background-color: var(--bx-default-button-hover-color);
+ }
+ }
+
+ &:active {
+ background-color: var(--bx-default-button-hover-color);
+ }
+
+ &:disabled + span {
+ font-family: var(--bx-title-font);
+ }
+ }
+
+ input[type=range]:disabled, button:disabled {
+ display: none;
+ }
+}
diff --git a/src/assets/css/remote-play.styl b/src/assets/css/remote-play.styl
new file mode 100644
index 0000000..51743c8
--- /dev/null
+++ b/src/assets/css/remote-play.styl
@@ -0,0 +1,123 @@
+.bx-remote-play-popup {
+ width: 100%;
+ max-width: 1920px;
+ margin: auto;
+ position: relative;
+ height: 0.1px;
+ overflow: visible;
+ z-index: var(--bx-remote-play-popup-z-index);
+}
+
+.bx-remote-play-container {
+ position: absolute;
+ right: 10px;
+ top: 0;
+ background: #1a1b1e;
+ border-radius: 10px;
+ width: 420px;
+ max-width: calc(100vw - 20px);
+ margin: 0 0 0 auto;
+ padding: 20px;
+ box-shadow: #00000080 0px 0px 12px 0px;
+
+ @media (min-width:480px) and (min-height:calc(480px + 1px)) {
+ right: calc(env(safe-area-inset-right, 0px) + 32px);
+ }
+
+ @media (min-width:768px) and (min-height:calc(480px + 1px)) {
+ right: calc(env(safe-area-inset-right, 0px) + 48px);
+ }
+
+ @media (min-width:1920px) and (min-height:calc(480px + 1px)) {
+ right: calc(env(safe-area-inset-right, 0px) + 80px);
+ }
+
+ > .bx-button {
+ display: table;
+ margin: 0 0 0 auto;
+ }
+}
+
+.bx-remote-play-settings {
+ margin-bottom: 12px;
+ padding-bottom: 12px;
+ border-bottom: 1px solid #2d2d2d;
+
+ > div {
+ display: flex;
+ }
+
+ label {
+ flex: 1;
+
+ p {
+ margin: 4px 0 0;
+ padding: 0;
+ color: #888;
+ font-size: 12px;
+ }
+ }
+
+ span {
+ font-weight: bold;
+ font-size: 18px;
+ display: block;
+ margin-bottom: 8px;
+ text-align: center;
+ }
+}
+
+.bx-remote-play-resolution {
+ display: block;
+
+ input[type="radio"] {
+ accent-color: var(--bx-primary-button-color);
+ margin-right: 6px;
+
+ &:focus {
+ accent-color: var(--bx-primary-button-hover-color);
+ }
+ }
+}
+
+.bx-remote-play-device-wrapper {
+ display: flex;
+ margin-bottom: 12px;
+
+ &:last-child {
+ margin-bottom: 2px;
+ }
+}
+
+.bx-remote-play-device-info {
+ flex: 1;
+ padding: 4px 0;
+}
+
+.bx-remote-play-device-name {
+ font-size: 20px;
+ font-weight: bold;
+ display: inline-block;
+ vertical-align: middle;
+}
+
+.bx-remote-play-console-type {
+ font-size: 12px;
+ background: #004c87;
+ color: #fff;
+ display: inline-block;
+ border-radius: 14px;
+ padding: 2px 10px;
+ margin-left: 8px;
+ vertical-align: middle;
+}
+
+.bx-remote-play-power-state {
+ color: #888;
+ font-size: 14px;
+}
+
+.bx-remote-play-connect-button {
+ min-height: 100%;
+ margin: 4px 0;
+}
diff --git a/src/assets/css/root.styl b/src/assets/css/root.styl
new file mode 100644
index 0000000..4ac4a7e
--- /dev/null
+++ b/src/assets/css/root.styl
@@ -0,0 +1,106 @@
+:root {
+ --bx-title-font: Bahnschrift, Arial, Helvetica, sans-serif;
+ --bx-title-font-semibold: Bahnschrift Semibold, Arial, Helvetica, sans-serif;
+ --bx-normal-font: "Segoe UI", Arial, Helvetica, sans-serif;
+ --bx-monospaced-font: Consolas, "Courier New", Courier, monospace;
+ --bx-promptfont-font: promptfont;
+
+ --bx-button-height: 36px;
+
+ --bx-default-button-color: #2d3036;
+ --bx-default-button-hover-color: #515863;
+ --bx-default-button-disabled-color: #8e8e8e;
+
+ --bx-primary-button-color: #008746;
+ --bx-primary-button-hover-color: #04b358;
+ --bx-primary-button-disabled-color: #448262;
+
+ --bx-danger-button-color: #c10404;
+ --bx-danger-button-hover-color: #e61d1d;
+ --bx-danger-button-disabled-color: #a26c6c;
+
+ --bx-toast-z-index: 9999;
+ --bx-reload-button-z-index: 9200;
+ --bx-dialog-z-index: 9101;
+ --bx-dialog-overlay-z-index: 9100;
+ --bx-remote-play-popup-z-index: 9090;
+ --bx-stats-bar-z-index: 9001;
+ --bx-stream-settings-z-index: 9000;
+ --bx-mkb-pointer-lock-msg-z-index: 8999;
+ --bx-screenshot-z-index: 8888;
+ --bx-touch-controller-bar-z-index: 5555;
+ --bx-wait-time-box-z-index: 100;
+}
+
+@font-face {
+ font-family: 'promptfont';
+ src: url('https://redphx.github.io/better-xcloud/fonts/promptfont.otf');
+}
+
+/* Fix Stream menu buttons not hiding */
+div[class^=HUDButton-module__hiddenContainer] ~ div:not([class^=HUDButton-module__hiddenContainer]) {
+ opacity: 0;
+ pointer-events: none !important;
+ position: absolute;
+ top: -9999px;
+ left: -9999px;
+}
+
+/* Remove the "Cloud Gaming" text in header when the screen is too small */
+@media screen and (max-width: 600px) {
+ header a[href="/play"] {
+ display: none;
+ }
+}
+
+.bx-full-width {
+ width: 100% !important;
+}
+
+.bx-full-height {
+ height: 100% !important;
+}
+
+.bx-no-scroll {
+ overflow: hidden !important;
+}
+
+.bx-gone {
+ display: none !important;
+}
+
+.bx-offscreen {
+ position: absolute !important;
+ top: -9999px !important;
+ left: -9999px !important;
+ visibility: hidden !important;
+}
+
+.bx-hidden {
+ visibility: hidden !important;
+}
+
+.bx-no-margin {
+ margin: 0 !important;
+}
+
+.bx-no-padding {
+ padding: 0 !important;
+}
+
+/* Hide UI elements */
+#headerArea, #uhfSkipToMain, .uhf-footer {
+ display: none;
+}
+
+div[class*=NotFocusedDialog] {
+ position: absolute !important;
+ top: -9999px !important;
+ left: -9999px !important;
+ width: 0px !important;
+ height: 0px !important;
+}
+
+#game-stream video:not([src]) {
+ visibility: hidden;
+}
diff --git a/src/assets/css/stream-actions.styl b/src/assets/css/stream-actions.styl
new file mode 100644
index 0000000..db6d1de
--- /dev/null
+++ b/src/assets/css/stream-actions.styl
@@ -0,0 +1,46 @@
+.bx-screenshot-button {
+ display: none;
+ opacity: 0;
+ position: fixed;
+ bottom: 0;
+ box-sizing: border-box;
+ width: 60px;
+ height: 90px;
+ padding: 16px 16px 46px 16px;
+ background-size: cover;
+ background-repeat: no-repeat;
+ background-origin: content-box;
+ filter: drop-shadow(0 0 2px #000000B0);
+ transition: opacity 0.1s ease-in-out 0s, padding 0.1s ease-in 0s;
+ z-index: var(--bx-screenshot-z-index);
+
+ /* Credit: https://phosphoricons.com */
+ background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDMyIDMyIiBmaWxsPSIjZmZmIj48cGF0aCBkPSJNMjguMzA4IDUuMDM4aC00LjI2NWwtMi4wOTctMy4xNDVhMS4yMyAxLjIzIDAgMCAwLTEuMDIzLS41NDhoLTkuODQ2YTEuMjMgMS4yMyAwIDAgMC0xLjAyMy41NDhMNy45NTYgNS4wMzhIMy42OTJBMy43MSAzLjcxIDAgMCAwIDAgOC43MzF2MTcuMjMxYTMuNzEgMy43MSAwIDAgMCAzLjY5MiAzLjY5MmgyNC42MTVBMy43MSAzLjcxIDAgMCAwIDMyIDI1Ljk2MlY4LjczMWEzLjcxIDMuNzEgMCAwIDAtMy42OTItMy42OTJ6bS02Ljc2OSAxMS42OTJjMCAzLjAzOS0yLjUgNS41MzgtNS41MzggNS41MzhzLTUuNTM4LTIuNS01LjUzOC01LjUzOCAyLjUtNS41MzggNS41MzgtNS41MzggNS41MzggMi41IDUuNTM4IDUuNTM4eiIvPjwvc3ZnPgo=');
+
+ &[data-showing=true] {
+ opacity: 0.9;
+ }
+
+ &[data-capturing=true] {
+ padding: 8px 8px 38px 8px;
+ }
+}
+
+.bx-screenshot-canvas {
+ display: none;
+}
+
+#bx-touch-controller-bar {
+ display: none;
+ opacity: 0;
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ height: 6vh;
+ z-index: var(--bx-touch-controller-bar-z-index);
+
+ &[data-showing=true] {
+ display: block;
+ }
+}
diff --git a/src/assets/css/stream-settings.styl b/src/assets/css/stream-settings.styl
new file mode 100644
index 0000000..1f066cd
--- /dev/null
+++ b/src/assets/css/stream-settings.styl
@@ -0,0 +1,133 @@
+.bx-quick-settings-bar {
+ display: flex;
+ position: fixed;
+ z-index: var(--bx-stream-settings-z-index);
+ opacity: 0.98;
+ user-select: none;
+ -webkit-user-select: none;
+}
+
+.bx-quick-settings-tabs {
+ position: fixed;
+ top: 0;
+ right: 420px;
+ display: flex;
+ flex-direction: column;
+ border-radius: 0 0 0 8px;
+ box-shadow: 0px 0px 6px #000;
+ overflow: clip;
+
+ svg {
+ width: 32px;
+ height: 32px;
+ padding: 10px;
+ box-sizing: content-box;
+ background: #131313;
+ cursor: pointer;
+ border-left: 4px solid #1e1e1e;
+
+ &.bx-active {
+ background: #222;
+ border-color: #008746;
+ }
+
+ &:not(.bx-active):hover {
+ background: #2f2f2f;
+ border-color: #484848;
+ }
+ }
+}
+
+
+.bx-quick-settings-tab-contents {
+ flex-direction: column;
+ position: fixed;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ padding: 14px 14px 0;
+ width: 420px;
+ background: #1a1b1e;
+ color: #fff;
+ font-weight: 400;
+ font-size: 16px;
+ font-family: var(--bx-title-font);
+ text-align: center;
+ box-shadow: 0px 0px 6px #000;
+ overflow: overlay;
+
+ > div[data-group=mkb] {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ overflow: hidden;
+ }
+
+ *:focus {
+ outline: none !important;
+ }
+
+ h2 {
+ margin-bottom: 8px;
+ display: flex;
+ align-item: center;
+
+ span {
+ display: inline-block;
+ font-size: 24px;
+ font-weight: bold;
+ text-transform: uppercase;
+ text-align: left;
+ flex: 1;
+ height: var(--bx-button-height);
+ line-height: calc(var(--bx-button-height) + 4px);
+ text-overflow: ellipsis;
+ overflow: hidden;
+ white-space: nowrap;
+ }
+ }
+
+ input[type="range"] {
+ display: block;
+ margin: 12px auto 2px;
+ width: 180px;
+ color: #959595 !important;
+ }
+}
+
+
+.bx-quick-settings-row {
+ display: flex;
+ border-bottom: 1px solid #40404080;
+ margin-bottom: 16px;
+ padding-bottom: 16px;
+
+ label {
+ font-size: 16px;
+ display: block;
+ text-align: left;
+ flex: 1;
+ align-self: center;
+ margin-bottom: 0 !important;
+ }
+
+ input {
+ accent-color: var(--bx-primary-button-color);
+ }
+
+ select:disabled {
+ -webkit-appearance: none;
+ background: transparent;
+ text-align-last: right;
+ border: none;
+ }
+}
+
+.bx-quick-settings-bar-note {
+ display: block;
+ text-align: center;
+ font-size: 12px;
+ font-weight: lighter;
+ font-style: italic;
+ padding-top: 16px;
+}
diff --git a/src/assets/css/stream-stats.styl b/src/assets/css/stream-stats.styl
new file mode 100644
index 0000000..5d523c8
--- /dev/null
+++ b/src/assets/css/stream-stats.styl
@@ -0,0 +1,145 @@
+/* STATS BADGE */
+.bx-badges {
+ position: absolute;
+ margin-left: 0px;
+ user-select: none;
+ -webkit-user-select: none;
+}
+
+.bx-badge {
+ border: none;
+ display: inline-block;
+ line-height: 24px;
+ color: #fff;
+ font-family: var(--bx-title-font-semibold);
+ font-size: 14px;
+ font-weight: 400;
+ margin: 0 8px 8px 0;
+ box-shadow: 0px 0px 6px #000;
+ border-radius: 4px;
+}
+
+.bx-badge-name {
+ background-color: #2d3036;
+ display: inline-block;
+ padding: 2px 8px;
+ border-radius: 4px 0 0 4px;
+ text-transform: uppercase;
+}
+
+.bx-badge-value {
+ background-color: grey;
+ display: inline-block;
+ padding: 2px 8px;
+ border-radius: 0 4px 4px 0;
+}
+
+.bx-badge-battery[data-charging=true] span:first-of-type::after {
+ content: ' ⚡️';
+}
+
+/* STATS BAR */
+.bx-stats-bar {
+ display: block;
+ user-select: none;
+ -webkit-user-select: none;
+ position: fixed;
+ top: 0;
+ background-color: #000;
+ color: #fff;
+ font-family: var(--bx-monospaced-font);
+ font-size: 0.9rem;
+ padding-left: 8px;
+ z-index: var(--bx-stats-bar-z-index);
+ text-wrap: nowrap;
+
+ &[data-stats*="[fps]"] > .bx-stat-fps,
+ &[data-stats*="[ping]"] > .bx-stat-ping,
+ &[data-stats*="[btr]"] > .bx-stat-btr,
+ &[data-stats*="[dt]"] > .bx-stat-dt,
+ &[data-stats*="[pl]"] > .bx-stat-pl,
+ &[data-stats*="[fl]"] > .bx-stat-fl {
+ display: inline-block;
+ }
+
+ &[data-stats$="[fps]"] > .bx-stat-fps,
+ &[data-stats$="[ping]"] > .bx-stat-ping,
+ &[data-stats$="[btr]"] > .bx-stat-btr,
+ &[data-stats$="[dt]"] > .bx-stat-dt,
+ &[data-stats$="[pl]"] > .bx-stat-pl,
+ &[data-stats$="[fl]"] > .bx-stat-fl {
+ margin-right: 0;
+ border-right: none;
+ }
+
+ &::before {
+ display: none;
+ content: '👀';
+ vertical-align: middle;
+ margin-right: 8px;
+ }
+
+ &[data-display=glancing]::before {
+ display: inline-block;
+ }
+
+ &[data-position=top-left] {
+ left: 0;
+ border-radius: 0 0 4px 0;
+ }
+
+ &[data-position=top-right] {
+ right: 0;
+ border-radius: 0 0 0 4px;
+ }
+
+ &[data-position=top-center] {
+ transform: translate(-50%, 0);
+ left: 50%;
+ border-radius: 0 0 4px 4px;
+ }
+
+ &[data-transparent=true] {
+ background: none;
+ filter: drop-shadow(1px 0 0 #000000f0) drop-shadow(-1px 0 0 #000000f0) drop-shadow(0 1px 0 #000000f0) drop-shadow(0 -1px 0 #000000f0);
+ }
+
+ > div {
+ display: none;
+ margin-right: 8px;
+ border-right: 1px solid #fff;
+ padding-right: 8px;
+ }
+
+ label {
+ margin: 0 8px 0 0;
+ font-family: var(--bx-title-font);
+ font-size: inherit;
+ font-weight: bold;
+ vertical-align: middle;
+ cursor: help;
+ }
+
+ span {
+ min-width: 60px;
+ display: inline-block;
+ text-align: right;
+ vertical-align: middle;
+
+ &[data-grade=good] {
+ color: #6bffff;
+ }
+
+ &[data-grade=ok] {
+ color: #fff16b;
+ }
+
+ &[data-grade=bad] {
+ color: #ff5f5f;
+ }
+
+ &:first-of-type {
+ min-width: 22px;
+ }
+ }
+}
diff --git a/src/assets/css/stream.styl b/src/assets/css/stream.styl
new file mode 100644
index 0000000..8d717ef
--- /dev/null
+++ b/src/assets/css/stream.styl
@@ -0,0 +1,9 @@
+div[class*=StreamMenu-module__menuContainer] > div[class*=Menu-module] {
+ overflow: visible;
+}
+
+.bx-stream-menu-button-on {
+ fill: #000 !important;
+ background-color: #2d2d2d !important;
+ color: #000 !important;
+}
diff --git a/src/assets/css/styles.styl b/src/assets/css/styles.styl
new file mode 100644
index 0000000..475bea2
--- /dev/null
+++ b/src/assets/css/styles.styl
@@ -0,0 +1,16 @@
+@import 'root.styl';
+
+@import 'button.styl';
+@import 'header.styl';
+@import 'global-settings.styl';
+@import 'dialog.styl';
+@import 'toast.styl';
+@import 'loading-screen.styl';
+@import 'remote-play.styl';
+
+@import 'stream.styl';
+@import 'number-stepper.styl';
+@import 'stream-actions.styl';
+@import 'stream-stats.styl';
+@import 'stream-settings.styl';
+@import 'mkb.styl';
diff --git a/src/assets/css/toast.styl b/src/assets/css/toast.styl
new file mode 100644
index 0000000..264c902
--- /dev/null
+++ b/src/assets/css/toast.styl
@@ -0,0 +1,45 @@
+.bx-toast {
+ user-select: none;
+ -webkit-user-select: none;
+ position: fixed;
+ left: 50%;
+ top: 24px;
+ transform: translate(-50%, 0);
+ background: #000000;
+ border-radius: 16px;
+ color: white;
+ z-index: var(--bx-toast-z-index);
+ font-family: var(--bx-normal-font);
+ border: 2px solid #fff;
+ display: flex;
+ align-items: center;
+ opacity: 0;
+ overflow: clip;
+ transition: opacity 0.2s ease-in;
+
+ &.bx-show {
+ opacity: 0.85;
+ }
+
+ &.bx-hide {
+ opacity: 0;
+ }
+}
+
+.bx-toast-msg {
+ font-size: 14px;
+ display: inline-block;
+ padding: 12px 16px;
+ white-space: pre;
+}
+
+.bx-toast-status {
+ font-weight: bold;
+ font-size: 14px;
+ text-transform: uppercase;
+ display: inline-block;
+ background: #515863;
+ padding: 12px 16px;
+ color: #fff;
+ white-space: pre;
+}
diff --git a/src/macros/build.ts b/src/macros/build.ts
new file mode 100644
index 0000000..0c2e9d5
--- /dev/null
+++ b/src/macros/build.ts
@@ -0,0 +1,13 @@
+import stylus from 'stylus';
+
+// @ts-ignore
+import cssStr from "../assets/css/styles.styl" with { type: "text" };
+
+const generatedCss = await (stylus(cssStr, {})
+ .set('filename', 'styles.css')
+ .include('src/assets/css/'))
+ .render();
+
+export const renderStylus = () => {
+ return generatedCss;
+};
diff --git a/src/utils/css.ts b/src/utils/css.ts
index 1736cfb..380acc1 100644
--- a/src/utils/css.ts
+++ b/src/utils/css.ts
@@ -1,1276 +1,10 @@
-import { CE, Icon } from "./html";
+import { CE } from "./html";
import { PrefKey, getPref } from "../modules/preferences";
+import { renderStylus } from "../macros/build" with {type: "macro"};
export function addCss() {
- let css = `
-:root {
- --bx-title-font: Bahnschrift, Arial, Helvetica, sans-serif;
- --bx-title-font-semibold: Bahnschrift Semibold, Arial, Helvetica, sans-serif;
- --bx-normal-font: "Segoe UI", Arial, Helvetica, sans-serif;
- --bx-monospaced-font: Consolas, "Courier New", Courier, monospace;
- --bx-promptfont-font: promptfont;
-
- --bx-button-height: 36px;
-
- --bx-default-button-color: #2d3036;
- --bx-default-button-hover-color: #515863;
- --bx-default-button-disabled-color: #8e8e8e;
-
- --bx-primary-button-color: #008746;
- --bx-primary-button-hover-color: #04b358;
- --bx-primary-button-disabled-color: #448262;
-
- --bx-danger-button-color: #c10404;
- --bx-danger-button-hover-color: #e61d1d;
- --bx-danger-button-disabled-color: #a26c6c;
-
- --bx-toast-z-index: 9999;
- --bx-reload-button-z-index: 9200;
- --bx-dialog-z-index: 9101;
- --bx-dialog-overlay-z-index: 9100;
- --bx-remote-play-popup-z-index: 9090;
- --bx-stats-bar-z-index: 9001;
- --bx-stream-settings-z-index: 9000;
- --bx-mkb-pointer-lock-msg-z-index: 8999;
- --bx-screenshot-z-index: 8888;
- --bx-touch-controller-bar-z-index: 5555;
- --bx-wait-time-box-z-index: 100;
-}
-
-@font-face {
- font-family: 'promptfont';
- src: url('https://redphx.github.io/better-xcloud/fonts/promptfont.otf');
-}
-
-/* Fix Stream menu buttons not hiding */
-div[class^=HUDButton-module__hiddenContainer] ~ div:not([class^=HUDButton-module__hiddenContainer]) {
- opacity: 0;
- pointer-events: none !important;
- position: absolute;
- top: -9999px;
- left: -9999px;
-}
-
-/* Remove the "Cloud Gaming" text in header when the screen is too small */
-@media screen and (max-width: 600px) {
- header a[href="/play"] {
- display: none;
- }
-}
-
-a.bx-button {
- display: inline-block;
-}
-
-.bx-button {
- background-color: var(--bx-default-button-color);
- user-select: none;
- -webkit-user-select: none;
- color: #fff;
- font-family: var(--bx-title-font-semibold);
- font-size: 14px;
- border: none;
- font-weight: 400;
- height: var(--bx-button-height);
- border-radius: 4px;
- padding: 0 8px;
- text-transform: uppercase;
- cursor: pointer;
- overflow: hidden;
-}
-
-.bx-button:focus {
- outline: none !important;
-}
-
-.bx-button:hover, .bx-button.bx-focusable:focus {
- background-color: var(--bx-default-button-hover-color);
-}
-
-.bx-button:disabled {
- cursor: default;
- background-color: var(--bx-default-button-disabled-color);
-}
-
-.bx-button.bx-ghost {
- background-color: transparent;
-}
-
-.bx-button.bx-ghost:hover, .bx-button.bx-ghost.bx-focusable:focus {
- background-color: var(--bx-default-button-hover-color);
-}
-
-.bx-button.bx-primary {
- background-color: var(--bx-primary-button-color);
-}
-
-.bx-button.bx-primary:hover, .bx-button.bx-primary.bx-focusable:focus {
- background-color: var(--bx-primary-button-hover-color);
-}
-
-.bx-button.bx-primary:disabled {
- background-color: var(--bx-primary-button-disabled-color);
-}
-
-.bx-button.bx-danger {
- background-color: var(--bx-danger-button-color);
-}
-
-.bx-button.bx-danger:hover, .bx-button.bx-danger.bx-focusable:focus {
- background-color: var(--bx-danger-button-hover-color);
-}
-
-.bx-button.bx-danger:disabled {
- background-color: var(--bx-danger-button-disabled-color);
-}
-
-.bx-button svg {
- display: inline-block;
- width: 16px;
- height: var(--bx-button-height);
-}
-
-.bx-button svg:not(:only-child) {
- margin-right: 4px;
-}
-
-.bx-button span {
- display: inline-block;
- height: calc(var(--bx-button-height) - 2px);
- line-height: var(--bx-button-height);
- vertical-align: middle;
- color: #fff;
- overflow: hidden;
- white-space: nowrap;
-}
-
-a.bx-button.bx-full-width {
- text-align: center;
-}
-
-.bx-header-remote-play-button {
- height: auto;
- margin-right: 8px !important;
-}
-
-.bx-header-remote-play-button svg {
- width: 24px;
- height: 46px;
-}
-
-.bx-header-settings-button {
- line-height: 30px;
- font-size: 14px;
- text-transform: uppercase;
-}
-
-.bx-header-settings-button[data-update-available]::before {
- content: '🌟' !important;
- line-height: var(--bx-button-height);
- display: inline-block;
- margin-left: 4px;
-}
-
-.bx-button.bx-focusable, .bx-header-settings-button {
- position: relative;
-}
-
-.bx-button.bx-focusable::after {
- border: 2px solid transparent;
- border-radius: 4px;
-}
-
-.bx-button.bx-focusable:focus::after {
- content: '';
- border-color: white;
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
-}
-
-.bx-settings-reload-button-wrapper {
- z-index: var(--bx-reload-button-z-index);
- position: fixed;
- bottom: 0;
- left: 0;
- right: 0;
- text-align: center;
- background: #000000cf;
- padding: 10px;
-}
-
-.bx-settings-reload-button-wrapper button {
- max-width: 450px;
- margin: 0 !important;
-}
-
-.bx-settings-container {
- background-color: #151515;
- user-select: none;
- -webkit-user-select: none;
- color: #fff;
- font-family: var(--bx-normal-font);
-}
-
-.bx-full-width {
- width: 100% !important;
-}
-
-.bx-full-height {
- height: 100% !important;
-}
-
-.bx-no-scroll {
- overflow: hidden !important;
-}
-
-.bx-gone {
- display: none !important;
-}
-
-.bx-offscreen {
- position: absolute !important;
- top: -9999px !important;
- left: -9999px !important;
- visibility: hidden !important;
-}
-
-.bx-hidden {
- visibility: hidden !important;
-}
-
-.bx-no-margin {
- margin: 0 !important;
-}
-
-.bx-no-padding {
- padding: 0 !important;
-}
-
-.bx-settings-wrapper {
- width: 450px;
- margin: auto;
- padding: 12px 6px;
-}
-
-@media screen and (max-width: 450px) {
- .bx-settings-wrapper {
- width: 100%;
- }
-}
-
-.bx-settings-wrapper *:focus {
- outline: none !important;
-}
-
-.bx-settings-wrapper .bx-settings-title-wrapper {
- display: flex;
- margin-bottom: 10px;
- align-items: center;
-}
-
-.bx-settings-wrapper a.bx-settings-title {
- font-family: var(--bx-title-font);
- font-size: 1.4rem;
- text-decoration: none;
- font-weight: bold;
- display: block;
- color: #5dc21e;
- flex: 1;
-}
-
-.bx-settings-group-label {
- font-weight: bold;
- display: block;
- font-size: 1.1rem;
-}
-
-@media (hover: hover) {
- .bx-settings-wrapper a.bx-settings-title:hover {
- color: #83f73a;
- }
-}
-
-.bx-settings-wrapper a.bx-settings-title:focus {
- color: #83f73a;
-}
-
-.bx-settings-wrapper a.bx-settings-update {
- display: block;
- color: #ff834b;
- text-decoration: none;
- margin-bottom: 8px;
- text-align: center;
- background: #222;
- border-radius: 4px;
- padding: 4px;
-}
-
-@media (hover: hover) {
- .bx-settings-wrapper a.bx-settings-update:hover {
- color: #ff9869;
- text-decoration: underline;
- }
-}
-
-.bx-settings-wrapper a.bx-settings-update:focus {
- color: #ff9869;
- text-decoration: underline;
-}
-
-.bx-settings-row {
- display: flex;
- margin-bottom: 8px;
- padding: 2px 4px;
-}
-
-.bx-settings-row label {
- flex: 1;
- align-self: center;
- margin-bottom: 0;
- padding-left: 10px;
-}
-
-.bx-settings-group-label b, .bx-settings-row label b {
- display: block;
- font-size: 12px;
- font-style: italic;
- font-weight: normal;
- color: #828282;
-}
-
-.bx-settings-group-label b {
- margin-bottom: 8px;
-}
-
-@media not (hover: hover) {
- .bx-settings-row:focus-within {
- background-color: #242424;
- }
-}
-
-.bx-settings-row input {
- align-self: center;
- accent-color: var(--bx-primary-button-color);
-}
-
-.bx-settings-row select:disabled {
- -webkit-appearance: none;
- background: transparent;
- text-align-last: right;
- border: none;
- color: #fff;
-}
-
-.bx-settings-wrapper .bx-button.bx-primary {
- margin-top: 8px;
-}
-
-.bx-settings-app-version {
- margin-top: 10px;
- text-align: center;
- color: #747474;
- font-size: 12px;
-}
-
-.bx-donation-link {
- display: block;
- text-align: center;
- text-decoration: none;
- height: 20px;
- line-height: 20px;
- font-size: 14px;
- margin-top: 10px;
- color: #5dc21e;
-}
-
-.bx-donation-link:hover {
- color: #6dd72b;
-}
-
-.bx-settings-custom-user-agent {
- display: block;
- width: 100%;
-}
-
-div[class*=StreamMenu-module__menuContainer] > div[class*=Menu-module] {
- overflow: visible;
-}
-
-.bx-badges {
- position: absolute;
- margin-left: 0px;
- user-select: none;
- -webkit-user-select: none;
-}
-
-.bx-badge {
- border: none;
- display: inline-block;
- line-height: 24px;
- color: #fff;
- font-family: var(--bx-title-font-semibold);
- font-size: 14px;
- font-weight: 400;
- margin: 0 8px 8px 0;
- box-shadow: 0px 0px 6px #000;
- border-radius: 4px;
-}
-
-.bx-badge-name {
- background-color: #2d3036;
- display: inline-block;
- padding: 2px 8px;
- border-radius: 4px 0 0 4px;
- text-transform: uppercase;
-}
-
-.bx-badge-value {
- background-color: grey;
- display: inline-block;
- padding: 2px 8px;
- border-radius: 0 4px 4px 0;
-}
-
-.bx-badge-battery[data-charging=true] span:first-of-type::after {
- content: ' ⚡️';
-}
-
-.bx-screenshot-button {
- display: none;
- opacity: 0;
- position: fixed;
- bottom: 0;
- box-sizing: border-box;
- width: 60px;
- height: 90px;
- padding: 16px 16px 46px 16px;
- background-size: cover;
- background-repeat: no-repeat;
- background-origin: content-box;
- filter: drop-shadow(0 0 2px #000000B0);
- transition: opacity 0.1s ease-in-out 0s, padding 0.1s ease-in 0s;
- z-index: var(--bx-screenshot-z-index);
-
- /* Credit: https://phosphoricons.com */
- background-image: url(${Icon.SCREENSHOT_B64});
-}
-
-.bx-screenshot-button[data-showing=true] {
- opacity: 0.9;
-}
-
-.bx-screenshot-button[data-capturing=true] {
- padding: 8px 8px 38px 8px;
-}
-
-.bx-screenshot-canvas {
- display: none;
-}
-
-.bx-stats-bar {
- display: block;
- user-select: none;
- -webkit-user-select: none;
- position: fixed;
- top: 0;
- background-color: #000;
- color: #fff;
- font-family: var(--bx-monospaced-font);
- font-size: 0.9rem;
- padding-left: 8px;
- z-index: var(--bx-stats-bar-z-index);
- text-wrap: nowrap;
-}
-
-.bx-stats-bar > div {
- display: none;
- margin-right: 8px;
- border-right: 1px solid #fff;
- padding-right: 8px;
-}
-
-.bx-stats-bar[data-stats*="[fps]"] > .bx-stat-fps,
-.bx-stats-bar[data-stats*="[ping]"] > .bx-stat-ping,
-.bx-stats-bar[data-stats*="[btr]"] > .bx-stat-btr,
-.bx-stats-bar[data-stats*="[dt]"] > .bx-stat-dt,
-.bx-stats-bar[data-stats*="[pl]"] > .bx-stat-pl,
-.bx-stats-bar[data-stats*="[fl]"] > .bx-stat-fl {
- display: inline-block;
-}
-
-.bx-stats-bar[data-stats$="[fps]"] > .bx-stat-fps,
-.bx-stats-bar[data-stats$="[ping]"] > .bx-stat-ping,
-.bx-stats-bar[data-stats$="[btr]"] > .bx-stat-btr,
-.bx-stats-bar[data-stats$="[dt]"] > .bx-stat-dt,
-.bx-stats-bar[data-stats$="[pl]"] > .bx-stat-pl,
-.bx-stats-bar[data-stats$="[fl]"] > .bx-stat-fl {
- margin-right: 0;
- border-right: none;
-}
-
-.bx-stats-bar::before {
- display: none;
- content: '👀';
- vertical-align: middle;
- margin-right: 8px;
-}
-
-.bx-stats-bar[data-display=glancing]::before {
- display: inline-block;
-}
-
-.bx-stats-bar[data-position=top-left] {
- left: 0;
- border-radius: 0 0 4px 0;
-}
-
-.bx-stats-bar[data-position=top-right] {
- right: 0;
- border-radius: 0 0 0 4px;
-}
-
-.bx-stats-bar[data-position=top-center] {
- transform: translate(-50%, 0);
- left: 50%;
- border-radius: 0 0 4px 4px;
-}
-
-.bx-stats-bar[data-transparent=true] {
- background: none;
- filter: drop-shadow(1px 0 0 #000000f0) drop-shadow(-1px 0 0 #000000f0) drop-shadow(0 1px 0 #000000f0) drop-shadow(0 -1px 0 #000000f0);
-}
-
-.bx-stats-bar label {
- margin: 0 8px 0 0;
- font-family: var(--bx-title-font);
- font-size: inherit;
- font-weight: bold;
- vertical-align: middle;
- cursor: help;
-}
-
-.bx-stats-bar span {
- min-width: 60px;
- display: inline-block;
- text-align: right;
- vertical-align: middle;
-}
-
-.bx-stats-bar span[data-grade=good] {
- color: #6bffff;
-}
-
-.bx-stats-bar span[data-grade=ok] {
- color: #fff16b;
-}
-
-.bx-stats-bar span[data-grade=bad] {
- color: #ff5f5f;
-}
-
-.bx-stats-bar span:first-of-type {
- min-width: 22px;
-}
-
-.bx-dialog-overlay {
- position: fixed;
- inset: 0;
- z-index: var(--bx-dialog-overlay-z-index);
- background: black;
- opacity: 50%;
-}
-
-.bx-dialog {
- display: flex;
- flex-flow: column;
- max-height: 90vh;
- position: fixed;
- top: 50%;
- left: 50%;
- margin-right: -50%;
- transform: translate(-50%, -50%);
- min-width: 420px;
- padding: 20px;
- border-radius: 8px;
- z-index: var(--bx-dialog-z-index);
- background: #1a1b1e;
- color: #fff;
- font-weight: 400;
- font-size: 16px;
- font-family: var(--bx-normal-font);
- box-shadow: 0 0 6px #000;
- user-select: none;
- -webkit-user-select: none;
-}
-
-.bx-dialog *:focus {
- outline: none !important;
-}
-
-@media screen and (max-width: 450px) {
- .bx-dialog {
- min-width: 100%;
- }
-}
-
-.bx-dialog h2 {
- display: flex;
- margin-bottom: 12px;
-}
-
-.bx-dialog h2 b {
- flex: 1;
- color: #fff;
- display: block;
- font-family: var(--bx-title-font);
- font-size: 26px;
- font-weight: 400;
- line-height: var(--bx-button-height);
-}
-
-.bx-dialog.bx-binding-dialog h2 b {
- font-family: var(--bx-promptfont-font) !important;
-}
-
-.bx-dialog > div {
- overflow: auto;
- padding: 2px 0;
-}
-
-.bx-dialog > button {
- padding: 8px 32px;
- margin: 10px auto 0;
- border: none;
- border-radius: 4px;
- display: block;
- background-color: #2d3036;
- text-align: center;
- color: white;
- text-transform: uppercase;
- font-family: var(--bx-title-font);
- font-weight: 400;
- line-height: 18px;
- font-size: 14px;
-}
-
-@media (hover: hover) {
- .bx-dialog > button:hover {
- background-color: #515863;
- }
-}
-
-.bx-dialog > button:focus {
- background-color: #515863;
-}
-
-.bx-stats-settings-dialog > div > div {
- display: flex;
- margin-bottom: 8px;
- padding: 2px 4px;
-}
-
-.bx-stats-settings-dialog label {
- flex: 1;
- margin-bottom: 0;
- align-self: center;
-}
-
-.bx-quick-settings-bar {
- display: flex;
- position: fixed;
- z-index: var(--bx-stream-settings-z-index);
- opacity: 0.98;
- user-select: none;
- -webkit-user-select: none;
-}
-
-.bx-quick-settings-tabs {
- position: fixed;
- top: 0;
- right: 420px;
- display: flex;
- flex-direction: column;
- border-radius: 0 0 0 8px;
- box-shadow: 0px 0px 6px #000;
- overflow: clip;
-}
-
-.bx-quick-settings-tabs svg {
- width: 32px;
- height: 32px;
- padding: 10px;
- box-sizing: content-box;
- background: #131313;
- cursor: pointer;
- border-left: 4px solid #1e1e1e;
-}
-
-.bx-quick-settings-tabs svg.bx-active {
- background: #222;
- border-color: #008746;
-}
-
-.bx-quick-settings-tabs svg:not(.bx-active):hover {
- background: #2f2f2f;
- border-color: #484848;
-}
-
-.bx-quick-settings-tab-contents {
- flex-direction: column;
- position: fixed;
- right: 0;
- top: 0;
- bottom: 0;
- padding: 14px 14px 0;
- width: 420px;
- background: #1a1b1e;
- color: #fff;
- font-weight: 400;
- font-size: 16px;
- font-family: var(--bx-title-font);
- text-align: center;
- box-shadow: 0px 0px 6px #000;
- overflow: overlay;
-}
-
-.bx-quick-settings-tab-contents > div[data-group=mkb] {
- display: flex;
- flex-direction: column;
- height: 100%;
- overflow: hidden;
-}
-
-.bx-quick-settings-tab-contents *:focus {
- outline: none !important;
-}
-
-.bx-quick-settings-row {
- display: flex;
- border-bottom: 1px solid #40404080;
- margin-bottom: 16px;
- padding-bottom: 16px;
-}
-
-.bx-quick-settings-row label {
- font-size: 16px;
- display: block;
- text-align: left;
- flex: 1;
- align-self: center;
- margin-bottom: 0 !important;
-}
-
-.bx-quick-settings-row input {
- accent-color: var(--bx-primary-button-color);
-}
-
-.bx-quick-settings-tab-contents h2 {
- margin-bottom: 8px;
- display: flex;
- align-item: center;
-}
-
-.bx-quick-settings-tab-contents h2 span {
- display: inline-block;
- font-size: 24px;
- font-weight: bold;
- text-transform: uppercase;
- text-align: left;
- flex: 1;
- height: var(--bx-button-height);
- line-height: calc(var(--bx-button-height) + 4px);
- text-overflow: ellipsis;
- overflow: hidden;
- white-space: nowrap;
-}
-
-.bx-quick-settings-tab-contents input[type="range"] {
- display: block;
- margin: 12px auto 2px;
- width: 180px;
- color: #959595 !important;
-}
-
-.bx-quick-settings-bar-note {
- display: block;
- text-align: center;
- font-size: 12px;
- font-weight: lighter;
- font-style: italic;
- padding-top: 16px;
-}
-
-.bx-toast {
- user-select: none;
- -webkit-user-select: none;
- position: fixed;
- left: 50%;
- top: 24px;
- transform: translate(-50%, 0);
- background: #000000;
- border-radius: 16px;
- color: white;
- z-index: var(--bx-toast-z-index);
- font-family: var(--bx-normal-font);
- border: 2px solid #fff;
- display: flex;
- align-items: center;
- opacity: 0;
- overflow: clip;
- transition: opacity 0.2s ease-in;
-}
-
-.bx-toast.bx-show {
- opacity: 0.85;
-}
-
-.bx-toast.bx-hide {
- opacity: 0;
-}
-
-.bx-toast-msg {
- font-size: 14px;
- display: inline-block;
- padding: 12px 16px;
- white-space: pre;
-}
-
-.bx-toast-status {
- font-weight: bold;
- font-size: 14px;
- text-transform: uppercase;
- display: inline-block;
- background: #515863;
- padding: 12px 16px;
- color: #fff;
- white-space: pre;
-}
-
-.bx-number-stepper span {
- display: inline-block;
- width: 40px;
- font-family: var(--bx-monospaced-font);
- font-size: 14px;
-}
-
-.bx-number-stepper button {
- border: none;
- width: 24px;
- height: 24px;
- margin: 0 4px;
- line-height: 24px;
- background-color: var(--bx-default-button-color);
- color: #fff;
- border-radius: 4px;
- font-weight: bold;
- font-size: 14px;
- font-family: var(--bx-monospaced-font);
- color: #fff;
-}
-
-@media (hover: hover) {
- .bx-number-stepper button:hover {
- background-color: var(--bx-default-button-hover-color);
- }
-}
-
-.bx-number-stepper button:active {
- background-color: var(--bx-default-button-hover-color);
-}
-
-.bx-number-stepper input[type=range]:disabled, .bx-number-stepper button:disabled {
- display: none;
-}
-
-.bx-number-stepper button:disabled + span {
- font-family: var(--bx-title-font);
-}
-
-.bx-mkb-settings {
- display: flex;
- flex-direction: column;
- flex: 1;
- padding-bottom: 10px;
- overflow: hidden;
-}
-
-.bx-mkb-settings select:disabled {
- -webkit-appearance: none;
- background: transparent;
- text-align-last: right;
- text-align: right;
- border: none;
- color: #fff;
-}
-
-.bx-quick-settings-row select:disabled {
- -webkit-appearance: none;
- background: transparent;
- text-align-last: right;
- border: none;
-}
-
-.bx-mkb-pointer-lock-msg {
- display: flex;
- cursor: pointer;
- user-select: none;
- -webkit-user-select: none;
- position: fixed;
- left: 50%;
- top: 50%;
- transform: translateX(-50%) translateY(-50%);
- margin: auto;
- background: #000000e5;
- z-index: var(--bx-mkb-pointer-lock-msg-z-index);
- color: #fff;
- text-align: center;
- font-weight: 400;
- font-family: "Segoe UI", Arial, Helvetica, sans-serif;
- font-size: 1.3rem;
- padding: 12px;
- border-radius: 8px;
- align-items: center;
- box-shadow: 0 0 6px #000;
-}
-
-.bx-mkb-pointer-lock-msg:hover {
- background: #151515;
-}
-
-.bx-mkb-pointer-lock-msg button {
- margin-right: 12px;
- height: 60px;
-}
-
-.bx-mkb-pointer-lock-msg svg {
- width: 32px;
-}
-
-.bx-mkb-pointer-lock-msg div {
- display: flex;
- flex-direction: column;
- text-align: left;
-}
-
-.bx-mkb-pointer-lock-msg p {
- margin: 0;
-}
-
-.bx-mkb-pointer-lock-msg p:first-child {
- font-size: 22px;
- margin-bottom: 8px;
-}
-
-.bx-mkb-pointer-lock-msg p:last-child {
- font-size: 14px;
- font-style: italic;
-}
-
-.bx-mkb-preset-tools {
- display: flex;
- margin-bottom: 12px;
-}
-
-.bx-mkb-preset-tools select {
- flex: 1;
-}
-
-.bx-mkb-preset-tools button {
- margin-left: 6px;
-}
-
-.bx-mkb-settings-rows {
- flex: 1;
- overflow: scroll;
-}
-
-.bx-mkb-key-row {
- display: flex;
- margin-bottom: 10px;
- align-items: center;
-}
-
-.bx-mkb-key-row label {
- margin-bottom: 0;
- font-family: var(--bx-promptfont-font);
- font-size: 26px;
- text-align: center;
- width: 26px;
- height: 32px;
- line-height: 32px;
-}
-
-.bx-mkb-key-row button {
- flex: 1;
- height: 32px;
- line-height: 32px;
- margin: 0 0 0 10px;
- background: transparent;
- border: none;
- color: white;
- border-radius: 0;
- border-left: 1px solid #373737;
-}
-
-.bx-mkb-key-row button:hover {
- background: transparent;
- cursor: default;
-}
-
-.bx-mkb-settings.bx-editing .bx-mkb-key-row button {
- background: #393939;
- border-radius: 4px;
- border: none;
-}
-
-.bx-mkb-settings.bx-editing .bx-mkb-key-row button:hover {
- background: #333;
- cursor: pointer;
-}
-
-.bx-mkb-action-buttons > div {
- text-align: right;
- display: none;
-}
-
-.bx-mkb-action-buttons button {
- margin-left: 8px;
-}
-
-.bx-mkb-settings:not(.bx-editing) .bx-mkb-action-buttons > div:first-child {
- display: block;
-}
-
-.bx-mkb-settings.bx-editing .bx-mkb-action-buttons > div:last-child {
- display: block;
-}
-
-.bx-mkb-note {
- display: block;
- margin: 16px 0 10px;
- font-size: 12px;
-}
-
-.bx-mkb-note:first-of-type {
- margin-top: 0;
-}
-
-
-.bx-stream-menu-button-on {
- fill: #000 !important;
- background-color: #2d2d2d !important;
- color: #000 !important;
-}
-
-#bx-touch-controller-bar {
- display: none;
- opacity: 0;
- position: fixed;
- bottom: 0;
- left: 0;
- right: 0;
- height: 6vh;
- z-index: var(--bx-touch-controller-bar-z-index);
-}
-
-#bx-touch-controller-bar[data-showing=true] {
- display: block;
-}
-
-.bx-wait-time-box {
- position: fixed;
- top: 0;
- right: 0;
- background-color: #000000cc;
- color: #fff;
- z-index: var(--bx-wait-time-box-z-index);
- padding: 12px;
- border-radius: 0 0 0 8px;
-}
-
-.bx-wait-time-box label {
- display: block;
- text-transform: uppercase;
- text-align: right;
- font-size: 12px;
- font-weight: bold;
- margin: 0;
-}
-
-.bx-wait-time-box span {
- display: block;
- font-family: var(--bx-monospaced-font);
- text-align: right;
- font-size: 16px;
- margin-bottom: 10px;
-}
-
-.bx-wait-time-box span:last-of-type {
- margin-bottom: 0;
-}
-
-/* REMOTE PLAY */
-
-.bx-container {
- width: 480px;
- margin: 0 auto;
-}
-
-#bxUi {
- margin-top: 14px;
-}
-
-.bx-remote-play-popup {
- width: 100%;
- max-width: 1920px;
- margin: auto;
- position: relative;
- height: 0.1px;
- overflow: visible;
- z-index: var(--bx-remote-play-popup-z-index);
-}
-
-.bx-remote-play-container {
- position: absolute;
- right: 10px;
- top: 0;
- background: #1a1b1e;
- border-radius: 10px;
- width: 420px;
- max-width: calc(100vw - 20px);
- margin: 0 0 0 auto;
- padding: 20px;
- box-shadow: #00000080 0px 0px 12px 0px;
-}
-
-@media (min-width:480px) and (min-height:calc(480px + 1px)) {
- .bx-remote-play-container {
- right: calc(env(safe-area-inset-right, 0px) + 32px)
- }
-}
-@media (min-width:768px) and (min-height:calc(480px + 1px)) {
- .bx-remote-play-container {
- right: calc(env(safe-area-inset-right, 0px) + 48px)
- }
-}
-@media (min-width:1920px) and (min-height:calc(480px + 1px)) {
- .bx-remote-play-container {
- right: calc(env(safe-area-inset-right, 0px) + 80px)
- }
-}
-
-.bx-remote-play-container > .bx-button {
- display: table;
- margin: 0 0 0 auto;
-}
-
-.bx-remote-play-settings {
- margin-bottom: 12px;
- padding-bottom: 12px;
- border-bottom: 1px solid #2d2d2d;
-}
-
-.bx-remote-play-settings > div {
- display: flex;
-}
-
-.bx-remote-play-settings label {
- flex: 1;
-}
-
-.bx-remote-play-settings label p {
- margin: 4px 0 0;
- padding: 0;
- color: #888;
- font-size: 12px;
-}
-
-.bx-remote-play-settings span {
- font-weight: bold;
- font-size: 18px;
- display: block;
- margin-bottom: 8px;
- text-align: center;
-}
-
-.bx-remote-play-resolution {
- display: block;
-}
-
-.bx-remote-play-resolution input[type="radio"] {
- accent-color: var(--bx-primary-button-color);
- margin-right: 6px;
-}
-
-.bx-remote-play-resolution input[type="radio"]:focus {
- accent-color: var(--bx-primary-button-hover-color);
-}
-
-.bx-remote-play-device-wrapper {
- display: flex;
- margin-bottom: 12px;
-}
-
-.bx-remote-play-device-wrapper:last-child {
- margin-bottom: 2px;
-}
-
-.bx-remote-play-device-info {
- flex: 1;
- padding: 4px 0;
-}
-
-.bx-remote-play-device-name {
- font-size: 20px;
- font-weight: bold;
- display: inline-block;
- vertical-align: middle;
-}
-
-.bx-remote-play-console-type {
- font-size: 12px;
- background: #004c87;
- color: #fff;
- display: inline-block;
- border-radius: 14px;
- padding: 2px 10px;
- margin-left: 8px;
- vertical-align: middle;
-}
-
-.bx-remote-play-power-state {
- color: #888;
- font-size: 14px;
-}
-
-.bx-remote-play-connect-button {
- min-height: 100%;
- margin: 4px 0;
-}
-
-/* ----------- */
-
-/* Hide UI elements */
-#headerArea, #uhfSkipToMain, .uhf-footer {
- display: none;
-}
-
-div[class*=NotFocusedDialog] {
- position: absolute !important;
- top: -9999px !important;
- left: -9999px !important;
- width: 0px !important;
- height: 0px !important;
-}
-
-#game-stream video:not([src]) {
- visibility: hidden;
-}
-`;
+ let css = renderStylus();
// Hide "Play with friends" section
if (getPref(PrefKey.BLOCK_SOCIAL_FEATURES)) {
diff --git a/src/utils/html.ts b/src/utils/html.ts
index ba247da..fed1618 100644
--- a/src/utils/html.ts
+++ b/src/utils/html.ts
@@ -68,8 +68,6 @@ export enum Icon {
REMOTE_PLAY = '',
HAND_TAP = '',
-
- SCREENSHOT_B64 = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDMyIDMyIiBmaWxsPSIjZmZmIj48cGF0aCBkPSJNMjguMzA4IDUuMDM4aC00LjI2NWwtMi4wOTctMy4xNDVhMS4yMyAxLjIzIDAgMCAwLTEuMDIzLS41NDhoLTkuODQ2YTEuMjMgMS4yMyAwIDAgMC0xLjAyMy41NDhMNy45NTYgNS4wMzhIMy42OTJBMy43MSAzLjcxIDAgMCAwIDAgOC43MzF2MTcuMjMxYTMuNzEgMy43MSAwIDAgMCAzLjY5MiAzLjY5MmgyNC42MTVBMy43MSAzLjcxIDAgMCAwIDMyIDI1Ljk2MlY4LjczMWEzLjcxIDMuNzEgMCAwIDAtMy42OTItMy42OTJ6bS02Ljc2OSAxMS42OTJjMCAzLjAzOS0yLjUgNS41MzgtNS41MzggNS41MzhzLTUuNTM4LTIuNS01LjUzOC01LjUzOCAyLjUtNS41MzggNS41MzgtNS41MzggNS41MzggMi41IDUuNTM4IDUuNTM4eiIvPjwvc3ZnPgo=',
};
export const createSvgIcon = (icon: string, strokeWidth=2) => {