Update site design/text to match new version

This commit is contained in:
hensm
2022-09-03 09:20:38 +01:00
committed by Matt Hensman
parent 28264cc8a0
commit 81ec06ba6d
37 changed files with 976 additions and 1001 deletions

4
docs/icons/apple.svg Normal file
View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512">
<!--! Font Awesome Pro 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. -->
<path fill="rgba(249, 249, 250, .8)" d="M318.7 268.7c-.2-36.7 16.4-64.4 50-84.8-18.8-26.9-47.2-41.7-84.7-44.6-35.5-2.8-74.3 20.7-88.5 20.7-15 0-49.4-19.7-76.4-19.7C63.3 141.2 4 184.8 4 273.5q0 39.3 14.4 81.2c12.8 36.7 59 126.7 107.2 125.2 25.2-.6 43-17.9 75.8-17.9 31.8 0 48.3 17.9 76.4 17.9 48.6-.7 90.4-82.5 102.6-119.3-65.2-30.7-61.7-90-61.7-91.9zm-56.6-164.2c27.3-32.4 24.8-61.9 24-72.5-24.1 1.4-52 16.4-67.9 34.9-17.5 19.8-27.8 44.3-25.6 71.9 26.1 2 49.9-11.4 69.5-34.3z" />
</svg>

After

Width:  |  Height:  |  Size: 726 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill="rgba(12, 12, 13, .8)" d="M8 12a1 1 0 0 1-.707-.293l-5-5a1 1 0 0 1 1.414-1.414L8 9.586l4.293-4.293a1 1 0 0 1 1.414 1.414l-5 5A1 1 0 0 1 8 12z"/></svg>

Before

Width:  |  Height:  |  Size: 244 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill="rgba(12, 12, 13, .8)" d="M7.293 12.707a1 1 0 0 0 1.414 0l5-5a1 1 0 0 0-1.414-1.414L9 9.586V1a1 1 0 1 0-2 0v8.586L3.707 6.293a1 1 0 0 0-1.414 1.414zM13 14H3a1 1 0 0 0 0 2h10a1 1 0 0 0 0-2z"/></svg>

Before

Width:  |  Height:  |  Size: 291 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill="rgba(12, 12, 13, .8)" d="M14.5 8c-.971 0-1 1-1.75 1a.765.765 0 0 1-.75-.75V5a1 1 0 0 0-1-1H7.75A.765.765 0 0 1 7 3.25c0-.75 1-.779 1-1.75C8 .635 7.1 0 6 0S4 .635 4 1.5c0 .971 1 1 1 1.75a.765.765 0 0 1-.75.75H1a1 1 0 0 0-1 1v2.25A.765.765 0 0 0 .75 8c.75 0 .779-1 1.75-1C3.365 7 4 7.9 4 9s-.635 2-1.5 2c-.971 0-1-1-1.75-1a.765.765 0 0 0-.75.75V15a1 1 0 0 0 1 1h3.25a.765.765 0 0 0 .75-.75c0-.75-1-.779-1-1.75 0-.865.9-1.5 2-1.5s2 .635 2 1.5c0 .971-1 1-1 1.75a.765.765 0 0 0 .75.75H11a1 1 0 0 0 1-1v-3.25a.765.765 0 0 1 .75-.75c.75 0 .779 1 1.75 1 .865 0 1.5-.9 1.5-2s-.635-2-1.5-2z"/></svg>

Before

Width:  |  Height:  |  Size: 684 B

4
docs/icons/fedora.svg Normal file
View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
<!--! Font Awesome Pro 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. -->
<path fill="rgba(249, 249, 250, .8)" d="M.0413 255.8C.1219 132.2 100.3 32 224 32C347.7 32 448 132.3 448 256C448 379.7 347.8 479.9 224.1 480H50.93C22.84 480 .0832 457.3 .0416 429.2H0V255.8H.0413zM342.6 192.7C342.6 153 307 124.2 269.4 124.2C234.5 124.2 203.6 150.5 199.3 184.1C199.1 187.9 198.9 189.1 198.9 192.6C198.8 213.7 198.9 235.4 198.1 257C199 283.1 199.1 309.1 198.1 333.6C198.1 360.7 178.7 379.1 153.4 379.1C128.1 379.1 107.6 358.9 107.6 333.6C108.1 305.9 130.2 288.3 156.1 287.5H156.3L182.6 287.3V250L156.3 250.2C109.2 249.8 71.72 286.7 70.36 333.6C70.36 379.2 107.9 416.5 153.4 416.5C196.4 416.5 232.1 382.9 236 340.9L236.2 287.4L268.8 287.1C294.1 287.3 293.8 249.3 268.6 249.8L236.2 250.1C236.2 243.7 236.3 237.3 236.3 230.9C236.4 218.2 236.4 205.5 236.2 192.7C236.3 176.2 252 161.5 269.4 161.5C286.9 161.5 305.3 170.2 305.3 192.7C305.3 195.9 305.2 197.8 305 199C303.1 209.5 310.2 219.4 320.7 220.9C331.3 222.4 340.9 214.8 341.9 204.3C342.5 200.1 342.6 196.4 342.6 192.7H342.6z" />
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,6 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill="rgba(249, 249, 250, .8)" d="M8 1a7 7 0 1 0 7 7 7.008 7.008 0 0 0-7-7zm0 13a6 6 0 1 1 6-6 6.007 6.007 0 0 1-6 6zm0-7a1 1 0 0 0-1 1v3a1 1 0 1 0 2 0V8a1 1 0 0 0-1-1zm0-3.188A1.188 1.188 0 1 0 9.188 5 1.188 1.188 0 0 0 8 3.812z"></path>
</svg>

After

Width:  |  Height:  |  Size: 551 B

View File

@@ -0,0 +1,6 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill="#d7b600" d="M14.742 12.106L9.789 2.2a2 2 0 0 0-3.578 0l-4.953 9.91A2 2 0 0 0 3.047 15h9.905a2 2 0 0 0 1.79-2.894zM7 5a1 1 0 0 1 2 0v4a1 1 0 0 1-2 0zm1 8.25A1.25 1.25 0 1 1 9.25 12 1.25 1.25 0 0 1 8 13.25z"></path>
</svg>

After

Width:  |  Height:  |  Size: 532 B

4
docs/icons/ubuntu.svg Normal file
View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512">
<!--! Font Awesome Pro 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. -->
<path fill="rgba(249, 249, 250, .8)" d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm52.7 93c8.8-15.2 28.3-20.5 43.5-11.7 15.3 8.8 20.5 28.3 11.7 43.6-8.8 15.2-28.3 20.5-43.5 11.7-15.3-8.9-20.5-28.4-11.7-43.6zM87.4 287.9c-17.6 0-31.9-14.3-31.9-31.9 0-17.6 14.3-31.9 31.9-31.9 17.6 0 31.9 14.3 31.9 31.9 0 17.6-14.3 31.9-31.9 31.9zm28.1 3.1c22.3-17.9 22.4-51.9 0-69.9 8.6-32.8 29.1-60.7 56.5-79.1l23.7 39.6c-51.5 36.3-51.5 112.5 0 148.8L172 370c-27.4-18.3-47.8-46.3-56.5-79zm228.7 131.7c-15.3 8.8-34.7 3.6-43.5-11.7-8.8-15.3-3.6-34.8 11.7-43.6 15.2-8.8 34.7-3.6 43.5 11.7 8.8 15.3 3.6 34.8-11.7 43.6zm.3-69.5c-26.7-10.3-56.1 6.6-60.5 35-5.2 1.4-48.9 14.3-96.7-9.4l22.5-40.3c57 26.5 123.4-11.7 128.9-74.4l46.1.7c-2.3 34.5-17.3 65.5-40.3 88.4zm-5.9-105.3c-5.4-62-71.3-101.2-128.9-74.4l-22.5-40.3c47.9-23.7 91.5-10.8 96.7-9.4 4.4 28.3 33.8 45.3 60.5 35 23.1 22.9 38 53.9 40.2 88.5l-46 .6z" />
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

4
docs/icons/windows.svg Normal file
View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
<!--! Font Awesome Pro 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. -->
<path fill="rgba(249, 249, 250, .8)" d="M0 93.7l183.6-25.3v177.4H0V93.7zm0 324.6l183.6 25.3V268.4H0v149.9zm203.8 28L448 480V268.4H203.8v177.9zm0-380.6v180.1H448V32L203.8 65.7z" />
</svg>

After

Width:  |  Height:  |  Size: 426 B

BIN
docs/images/menu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

BIN
docs/images/menu.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 388 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

BIN
docs/images/preview.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

BIN
docs/images/preview.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

View File

@@ -1,13 +1,7 @@
:root.theme-light {
--page-color: var(--grey-10);
--text-color-primary: var(--grey-90);
--text-color-secondary: var(--grey-50);
}
:root.theme-dark {
--page-color: var(--grey-80);
:root {
--page-color: #1c1b22;
--text-color-primary: var(--white-100);
--text-color-secondary: var(--grey-30);
--text-color-secondary: var(--grey-10-a60);
}
* {
@@ -20,8 +14,13 @@ body {
width: 100%;
}
h1, h2, h3, h4, h5, h6 {
margin: initial;
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 0.75em 0;
font-size: inherit;
font-weight: 600;
}
@@ -31,13 +30,15 @@ p {
}
ul {
margin: initial;
margin: 0.75em 0;
padding: initial;
}
:root {
color: var(--text-color-primary);
--system-font: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
--system-font: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji",
"Segoe UI Emoji", "Segoe UI Symbol";
font-family: var(--system-font);
font-size: 10px;
}
@@ -50,90 +51,107 @@ body {
z-index: -1;
}
.container {
display: grid;
font-size: 1.5rem;
margin: auto;
margin-top: initial;
grid-row-gap: 2rem;
grid-template-areas:
"header preview"
"description preview"
"download preview"
"faqs faqs"
"footer footer";
grid-template-columns: 45rem minmax(0, auto);
grid-template-rows: min-content minmax(200px, auto) 1fr min-content min-content;
overflow-x: hidden;
padding: 2rem;
.disclaimer {
color: var(--text-color-secondary);
font-size: 0.85em;
padding-left: calc(16px + 0.5em);
position: relative;
}
.disclaimer::before {
background-image: url("icons/photon_info.svg");
content: "";
display: block;
flex-shrink: 0;
left: 0;
height: 16px;
position: absolute;
width: 16px;
}
.disclaimer--warning {
color: var(--yellow-60);
font-weight: 600;
}
.disclaimer--warning::before {
background-image: url("icons/photon_warning.svg");
}
.container h1 { font-size: 2.2rem ;}
.container h2 { font-size: 2.0rem ;}
.container h3 { font-size: 1.8rem ;}
.container h4 { font-size: 1.6rem ;}
.container h5,
.container h6 { font-size: 1.5rem ;}
.disclaimer--warning a,
.disclaimer--warning a:hover {
color: var(--yellow-70);
}
.disclaimer--warning a:hover:active {
color: var(--yellow-80);
}
.container {
font-size: 1.5rem;
width: 100%;
}
.container h1 {
font-size: 2.2rem;
}
.container h2 {
font-size: 2rem;
}
.container h3 {
font-size: 1.8rem;
}
.container h4 {
font-size: 1.6rem;
}
.container h5,
.container h6 {
font-size: 1.5rem;
}
.site-header {
align-self: flex-end;
align-items: flex-end;
align-items: start;
display: flex;
flex-direction: column;
font-family: "SF Mono", var(--system-font);
grid-area: header;
justify-content: flex-end;
margin-top: 5rem;
height: 105px;
margin-top: 2rem;
}
h1.site-header__title {
font-size: 5rem;
font-weight: 500;
font-weight: 600;
margin: initial;
margin-bottom: 0.5rem;
}
.site-header__subtitle {
background-color: var(--text-color-secondary);
color: var(--page-color);
font-size: 2.2rem;
margin-right: -1rem;
margin: initial;
margin-left: -1rem;
padding: 0.25rem 1rem;
text-transform: lowercase;
}
.site-content {
display: contents;
.page-width {
max-width: 1000px;
margin: 0 auto;
padding: 1rem 4rem;
}
.entry {
display: flex;
gap: 2rem;
}
.description {
font-size: 1.75rem;
grid-area: description;
font-size: 1.65rem;
max-width: 45rem;
padding-right: 4rem;
text-align: right;
}
.description__disclaimer {
color: var(--text-color-secondary);
font-size: 0.85em;
.description p:not(:first-child) {
margin: 1em 0;
}
.description__prerelease {
color: var(--red-50);
font-size: 0.85em;
font-weight: bolder;
}
.description p {
margin: 1rem 0;
}
.download {
align-items: flex-end;
margin-top: 3rem;
align-items: start;
display: flex;
flex-direction: column;
grid-area: download;
margin-top: 1rem;
position: relative;
}
@@ -142,6 +160,7 @@ h1.site-header__title {
font-size: 1.75rem;
font-weight: 600;
margin-bottom: 0.5em;
white-space: nowrap;
}
.download__ext[data-version]::after,
@@ -152,129 +171,89 @@ h1.site-header__title {
opacity: 0.75;
}
.download__app-other {
margin-top: 1em;
}
.download__app-other > summary {
cursor: pointer;
text-align: right;
margin-bottom: 0.5rem;
}
.download__app-other > summary > h3 {
display: inline;
font: inherit;
}
.app-list {
display: flex;
flex-direction: column;
}
.app-list__platform {
display: contents;
}
.app-list__app:not(.button) {
color: var(--blue-50);
position: relative;
padding-right: 50px;
text-decoration: initial;
}
.app-list__app:not(.button):hover {
text-decoration: underline;
}
.app-list__app:not(.button):active {
color: var(--blue-60);
}
.app-list__app:not(.button)[data-file-size]::after {
content: "(" attr(data-file-size) ")";
.download__ext::before,
.download__app::before,
.button[data-platform]::before {
background-repeat: no-repeat;
background-size: 100% 100%;
content: "";
display: block;
position: absolute;
right: 0;
top: 0;
cursor: initial;
}
.button[data-platform]::before {
height: 16px;
margin-right: 6px;
width: 16px;
}
.button.download__ext::before,
.button.download__app::before {
height: 20px;
width: 20px;
margin-right: 8px;
}
.download__ext::before {
background-image: url("icons/extension_light.svg");
}
.button[data-platform="win"]::before {
background-image: url("icons/windows.svg");
}
.button[data-platform="mac"]::before {
background-image: url("icons/apple.svg");
}
.button[data-platform="deb"]::before {
background-image: url("icons/ubuntu.svg");
}
.button[data-platform="rpm"]::before {
background-image: url("icons/fedora.svg");
}
h3.download__bridge-header {
color: var(--text-color-secondary);
font-size: 1em;
}
.app-list--buttons {
align-items: flex-start;
.download__bridge-primary {
display: flex;
flex-direction: row;
gap: 0.5rem;
}
.app-list--buttons > *:not(:first-child) {
margin-left: 1rem;
.download__bridge-all {
margin-top: 1em;
display: flex;
gap: 1rem;
}
.app-list--buttons .app-list__platform {
.download__bridge-list {
margin-top: 1em;
display: flex;
gap: 1rem;
}
.download__bridge-list > div {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.download__bridge-list .button {
height: 42px;
white-space: nowrap;
}
.app-list--buttons .app-list__app {
cursor: pointer;
min-width: initial !important;
}
.app-list--buttons > .app-list__platform > .app-list__app + .app-list__app {
margin-top: 0.5rem;
}
.app-list--buttons .app-list__app-link {
display: inline-flex;
}
.app-list--buttons .app-list__app-label {
color: var(--blue-40);
.app-tag {
font-size: 0.8em;
font-variant: small-caps;
opacity: 0.5;
margin-left: 0.5em;
vertical-align: super;
}
.preview {
grid-area: preview;
-moz-user-select: none;
-webkit-user-select: none;
user-select: none;
z-index: -1;
align-self: start;
display: flex;
flex-wrap: wrap;
margin-left: -36px;
margin-right: -4rem;
margin-top: -72px;
overflow: hidden;
}
.preview--bg {
-webkit-mask-image: linear-gradient(to right, black, transparent);
mask-image: linear-gradient(to right, black, transparent);
height: 668px;
object-fit: cover;
object-position: left;
opacity: 0.65;
width: 700px;
}
.preview--fg {
align-self: flex-start;
grid-row-start: 2;
margin-top: 1rem;
}
.preview--fg[src="images/preview-fg_dark.png"],
.preview--fg[src="images/preview-fg_dark@2x.png"],
.preview--fg[src="images/preview-fg_light.png"],
.preview--fg[src="images/preview-fg_light@2x.png"] {
transform: translate(-55px, -36px);
}
.faqs {
grid-area: faqs;
background-color: #15141a;
border-width: 0.5rem 0;
position: relative;
z-index: 1;
}
@@ -286,10 +265,12 @@ h1.site-header__title {
margin: 1rem 0;
}
.faq {
border: 2px solid transparent;
border-radius: 5px;
background-color: #1c1b22;
box-sizing: content-box;
padding: 0 1rem;
}
.faq:target {
@@ -307,13 +288,13 @@ h1.site-header__title {
.faq__summary > h3 {
display: inline;
margin: initial;
}
.faq__content {
max-width: 80rem;
overflow-x: auto;
padding: 2rem;
padding-top: 1rem;
padding: 1rem;
padding-top: 0;
}
.faq__content p {
@@ -324,76 +305,51 @@ h1.site-header__title {
}
.faq__content code {
background-color: var(--grey-90-a10);
border-radius: 3px;
white-space: pre;
}
:root.theme-dark .faq {
background-color: #202023;
}
:root.theme-dark .faq[open],
:root.theme-dark .faq:hover {
border: 5px solid var(--grey-60);
}
:root.theme-dark .faq code {
background-color: var(--grey-10-a10);
border-radius: 3px;
white-space: nowrap;
}
.footer {
align-items: center;
display: flex;
flex-direction: column;
font-size: 1.5rem;
grid-area: footer;
justify-content: center;
margin-top: 5rem;
padding: 2rem 0;
}
.links__link-github {
align-items: center;
display: flex;
justify-content: center;
}
:root.theme-dark .links__link-github img {
.github-link {
display: block;
filter: invert(1);
margin: 0 auto;
text-align: center;
}
@media (max-width: 700px) {
.container {
align-items: center;
display: flex;
flex-direction: column;
gap: 0;
padding: initial;
}
.site-content > section {
.page-width {
padding: 2rem;
}
.entry {
align-items: center;
flex-direction: column;
}
.site-header,
.preview--fg {
.preview {
order: -1;
}
.preview--bg {
display: none;
}
.preview--fg {
.preview {
align-self: center;
margin: initial;
margin-bottom: -50px;
max-width: 100vw;
object-fit: cover;
overflow: visible;
transform: initial !important;
margin-top: -36px;
}
.preview > img {
max-width: 100%;
}
.site-header {
@@ -405,19 +361,30 @@ h1.site-header__title {
.site-header__subtitle {
margin-right: initial;
text-align: center;
width: 100vw;
}
.description {
padding-right: initial;
text-align: center;
margin-top: -30px;
max-width: initial;
width: initial;
}
.download {
align-items: center;
margin: initial;
.download__bridge-primary {
flex-wrap: wrap;
}
.download__bridge-all {
width: 100%;
}
.download__bridge-list {
align-items: start;
flex-wrap: wrap;
width: 100%;
}
.download__bridge-list > div {
display: contents;
}
.download__bridge-list .button {
height: 36px;
}
.faqs {
@@ -442,7 +409,7 @@ h1.site-header__title {
.faq__content {
display: flex;
flex-direction: column;
padding: .5rem;
padding: 0.5rem;
}
.faq__content p {

View File

@@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en" class="theme-dark">
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
@@ -23,117 +23,74 @@
</head>
<body>
<div class="container">
<div class="page-width">
<header class="site-header">
<h1 class="site-header__title">fx_cast</h1>
<p class="site-header__subtitle">
Chromecast <nobr>for Firefox</nobr>
</p>
</header>
</div>
<main class="site-content">
<section class="description">
<h2 hidden>Description</h2>
<div class="page-width">
<section class="entry">
<div>
<div class="description">
<p>
A browser extension that enables Chromecast support for
casting web apps (like YouTube, Netflix or BBC iPlayer),
HTML5 media and <nobr>screen/tab sharing</nobr>.
A Firefox extension that enables Chromecast
support for casting web apps (like YouTube,
Netflix or BBC iPlayer) and HTML5 media.
</p>
<p class="description__disclaimer">
Requires a native bridge app to connect with receiver
devices. Currently supported on Windows, macOS and
Linux.
<p class="disclaimer">
Requires a companion bridge application to
connect with receiver devices. Currently
supported on Windows, macOS and Linux.
</p>
<p class="description__prerelease">
No full public release yet! Pre-release beta version is
incomplete and likely buggy.
<p class="disclaimer disclaimer--warning">
The current v0.x.x releases are incomplete
and may be unstable.
</p>
<p class="description__disclaimer">
Latest release is missing macOS x86 build and Windows
32-bit build. See
<a href="https://github.com/hensm/fx_cast/issues/209"
>#209</a
>
for more info. Older releases are
<a href="https://github.com/hensm/fx_cast/releases"
>available</a
>.
</p>
</section>
<section class="download">
</div>
<div class="download">
<h2 hidden>Downloads</h2>
<a
class="download__ext button button--puffy button--primary"
title="No available download found"
disabled
>
<img
class="button__icon"
src="icons/extension_light.svg"
alt="Extension symbol (puzzle) icon"
/>
Firefox Extension
</a>
<a
class="download__app button button--puffy"
title="No available download found"
disabled
>
</a>
<details class="download__app-other">
<summary>
<h3>Other bridge downloads</h3>
</summary>
<div class="app-list">
<a
class="app-list__app app-list__mac"
title="No available download found"
disabled
>
macOS
</a>
<div class="app-list__platform">
<a
class="app-list__app app-list__win64"
title="No available download found"
disabled
>
Windows
<span class="app-list__app-label">x64</span>
</a>
<a
class="app-list__app app-list__win32"
title="No available download found"
disabled
>
Windows
<span class="app-list__app-label">x86</span>
</a>
</div>
<div class="app-list__platform">
<a
class="app-list__app app-list__deb"
title="No available download found"
disabled
>
Linux
<span class="app-list__app-label">DEB</span>
</a>
<a
class="app-list__app app-list__rpm"
title="No available download found"
disabled
>
Linux
<span class="app-list__app-label">RPM</span>
</a>
</div>
</div>
<div class="download__bridge-primary"></div>
<details class="download__bridge-all">
<summary>Other bridge downloads</summary>
<div class="download__bridge-list"></div>
</details>
</div>
</div>
<picture class="preview">
<source
type="image/webp"
srcset="images/preview.webp"
/>
<source
type="image/png"
srcset="images/preview.png"
/>
<img
alt="Screenshot, receiver selector popup."
width="512"
src="images/preview.png"
/>
</picture>
</section>
</div>
<section class="faqs">
<div class="page-width">
<h2>FAQs</h2>
<ul class="faqs__list">
<li class="faqs__list-item">
<details class="faq card" open>
<details class="faq" open>
<summary class="faq__summary">
<h3>How do I cast something?</h3>
</summary>
@@ -141,105 +98,87 @@
<picture style="float: right">
<source
type="image/webp"
srcset="
images/webp/menu_light.webp,
images/webp/menu_light@2x.webp 2x
"
media="(prefers-color-scheme: light)"
/>
<source
type="image/webp"
srcset="
images/webp/menu_dark.webp,
images/webp/menu_dark@2x.webp 2x
"
media="(prefers-color-scheme: dark)"
srcset="images/menu.webp"
/>
<source
type="image/png"
srcset="
images/menu_light.png,
images/menu_light@2x.png 2x
"
media="(prefers-color-scheme: light)"
/>
<source
type="image/png"
srcset="
images/menu_dark.png,
images/menu_dark@2x.png 2x
"
media="(prefers-color-scheme: dark)"
srcset="images/menu.png"
/>
<img
alt="Screenshot, media context menu."
src="images/menu_dark.png"
src="images/menu.png"
width="270"
/>
</picture>
<h4>Sites with Chromecast support</h4>
<p>
For sites with built-in cast support,
click the cast button in the page and
select the destination in the receiver
selector popup. You may have to add the
site to the whitelist to get the cast
button to appear.
For sites with built-in Chromecast
support, the site must be added to
the site to the whitelist to get the
cast button to appear. You can
easily add a site to the whitelist
from the toolbar button context
menu.
</p>
<p>
For other sites, there is a "Cast..."
item in the context menu when
right-clicking on a media player. This
may not be visible depending on whether
the site has chosen to obscure the
player with an overlay or if the media
is DRM-encumbered (see below).
Once whitelisted, reload the page
and click the cast button in the
player controls to start casting.
</p>
<p class="disclaimer">
Not all sites are well-supported and
you may encounter issues.
<a href="#Why_doesn't_𝑥_site_work?"
>See below</a
>, for more info.
</p>
<h4>HTML5 Media</h4>
<p>
For certain types of media, there is
a "Cast..." menu item in the browser
context menu for the media player
(if the player has a custom context
menu, try shift-clicking to bring up
the browser context menu).
</p>
<p>
Clicking the toolbar button will open
the popup, but depending on the context,
it may not be possible to cast anything.
</p>
<p>
As a last resort, casting the tab or
screen may provide a means of displaying
this media on the Chromecast, but it has
its own limitations: the performance is
very poor and there's no audio casting.
This may not be visible depending on
whether the media is
<a
href="#Why_can't_I_cast_DRM-encumbered_media?"
>DRM-encumbered</a
>
or has a network-accessible URL to
send to the Chromecast device.
</p>
<div style="clear: right"></div>
</div>
</details>
</li>
<li class="faqs__list-item">
<details class="faq card">
<details class="faq">
<summary class="faq__summary">
<h3>Why do I need the bridge?</h3>
</summary>
<div class="faq__content">
<p>Access to TCP/UDP sockets.</p>
<p>
Network discovery for Chromecast devices
relies on mDNS, the implementation of
which is reliant on being able to send
UDP packets. Communication with the
Chromecast device itself relies on a TCP
connection. The current workaround is to
offload that work to a native companion
application that the extension can then
launch and communicate with.
</p>
<p>
It's possible that this functionality
will be re-exposed to extensions, in
which case the bridge will be made
redundant:
API limitations. Chromecast device
discovery requires an mDNS/DNS-SD
implementation, something which
isn't provided by (or possible with)
WebExtension APIs. Communicating
with Chromecast devices require
making TCP connections, which is
also not possible.
</p>
<p>Relevant Firefox bugs:</p>
<ul>
<li>
<a
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1247628"
>bug 1247628 — Enable "TCP and
UDP Socket API" for
>bug 1247628 — Enable "TCP
and UDP Socket API" for
WebExtensions</a
>
</li>
@@ -247,8 +186,8 @@
<a
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1461830"
>bug 1461830 — [experimental
api] mDNS APIs for IoT and p2p
extensions</a
api] mDNS APIs for IoT and
p2p extensions</a
>
</li>
</ul>
@@ -256,52 +195,136 @@
</details>
</li>
<li class="faqs__list-item">
<details class="faq card">
<details class="faq">
<summary class="faq__summary">
<h3>
"No bridge found" with Firefox
snap/Flatpak package
Why aren't my devices being found?
</h3>
</summary>
<div class="faq__content">
<p>
The bridge relies on system services
(Bonjour on Windows/macOS, Avahi on
Linux) to provide device discovery.
If the bridge isn't able to find any
devices, there may be a
configuration issue (either with the
system service or the network).
</p>
<p class="disclaimer">
If you're using Arch Linux, Avahi is
not configured by default to resolve
<code>.local</code> hostnames via
the
<abbr title="Name Service Switch"
>NSS</abbr
>
which is required to resolve
Chromecast device addresses. See
more information
<a
href="https://wiki.archlinux.org/title/avahi#Hostname_resolution"
>here</a
>.
</p>
<p>Other issues include:</p>
<ul>
<li>
The devices you're looking for
may not be compatible. Chrome
also supports a limited number
of apps on some Smart TVs via an
older protocol called
<abbr
title="DIscovery And Launch"
>DIAL</abbr
>
which
<a
href="https://github.com/hensm/fx_cast/issues/7"
>isn't currently
supported</a
>.
</li>
<li>
<p>
Some network configurations
may interfere with mDNS
packets. Virtual machine
network adapters typically
will not work out of the
box, for example.
</p>
</li>
<li>
<p>
There may be an issue with
the bridge causing it to
close unexpectedly. Check
the
<a
href="https://firefox-source-docs.mozilla.org/devtools-user/browser_console/index.html"
>Browser Console</a
>
for error logs and submit a
new issue on GitHub with
some more information (if
necessary).
</p>
</li>
</ul>
</div>
</details>
</li>
<li class="faqs__list-item">
<details class="faq">
<summary class="faq__summary">
<h3>
Why isn't the bridge found when
using the Firefox snap/Flatpak
package?
</h3>
</summary>
<div class="faq__content">
<p>
Whilst running inside a sandboxed
version of Firefox, the extension is
unable to start the bridge by itself.
The bridge must be started in
unable to start the bridge by
itself. The bridge must be started
in
<a
href="https://github.com/hensm/fx_cast/#daemon-configuration"
>daemon mode</a
>, and the
<i>"Enable backup daemon connection"</i>
<i
>"Enable backup daemon
connection"</i
>
option enabled in the extension.
</p>
</div>
</details>
</li>
<li class="faqs__list-item">
<details class="faq card">
<details class="faq">
<summary class="faq__summary">
<h3>
How do I completely remove the bridge?
How do I completely remove the
bridge?
</h3>
</summary>
<div class="faq__content">
<ul>
<li>
<h4>Windows</h4>
<p>
Removing the bridge on Windows
should be as easy as running the
uninstaller (<code
>C:\Program
Files\fx_cast\uninstaller.exe</code
>) found in the control panel or
settings application.
uninstaller found in the control
panel, settings application, or
application directory.
</p>
<p>
To manually uninstall, remove
the following files/folders and
To manually uninstall, remove the
following files/directories and
registry keys:
</p>
<ul>
@@ -323,12 +346,11 @@
>
</li>
</ul>
</li>
<li>
<h4>macOS</h4>
<p>
Remove the following
files/folders:
files/directories:
</p>
<ul>
<li>
@@ -344,20 +366,24 @@
>
</li>
</ul>
</li>
<li>
<h4>Linux</h4>
<p class="disclaimer">
For third-party packages, check the
documentation provided by the
package maintainer.
</p>
<p>
On Debian-based systems, remove
the
On Debian-based systems, remove the
<code>fx-cast-bridge</code>
package, otherwise remove the
package, otherwise for Fedora-based
systems, remove the
<code>fx_cast_bridge</code>
package.
</p>
<p>
To manually uninstall, remove
the following files/folders:
To manually uninstall, remove the
following files/directories:
</p>
<ul>
<li>
@@ -367,7 +393,6 @@
<code
>/usr/lib/mozilla/native-messaging-hosts/fx_cast_bridge.json</code
>
OR
</li>
<li>
<code
@@ -375,13 +400,11 @@
>
</li>
</ul>
</li>
</ul>
</div>
</details>
</li>
<li class="faqs__list-item">
<details class="faq card">
<details class="faq">
<summary class="faq__summary">
<h3>
Why is there no sound when casting a
@@ -390,11 +413,13 @@
</summary>
<div class="faq__content">
<p>
API limitations. There's no method of
obtaining the audio streams. Merging of
audio streams from remote media is also
not possible due to cross-origin issues.
API limitations. There's no method
of obtaining the audio streams.
Merging of audio streams from remote
media is also not possible due to
cross-origin issues.
</p>
<p>Relevant Firefox bugs:</p>
<ul>
<li>
<a
@@ -406,8 +431,9 @@
<li>
<a
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1541425"
>bug 1541425 — Implement audio
capture for getDisplayMedia</a
>bug 1541425 — Implement
audio capture for
getDisplayMedia</a
>
</li>
</ul>
@@ -415,29 +441,29 @@
</details>
</li>
<li class="faqs__list-item">
<details class="faq card">
<details class="faq">
<summary class="faq__summary">
<h3>Why doesn't 𝑥 site work?</h3>
</summary>
<div class="faq__content">
<p>
Compatibility with Chrome is far from
perfect. Most sites will only enable
their cast support if the browser
reports itself as Chrome. Ensure that
you've added the site to the whitelist.
Some sites may not test their
Chrome-specific code with Firefox, so
it's possible that they're using
Compatibility with Chrome is far
from perfect. Most sites will only
enable their cast support if the
browser reports itself as Chrome, so
ensure that you've added the site to
the whitelist. Some sites may not
test their Chrome-specific code with
Firefox, so it's possible that
they're using
incompatible/non-standard APIs.
</p>
<p>
The API is also not fully implemented
and is missing some methods (mostly
queue management). The current
implementation likely also has
edge-cases and bugs which may cause
issues.
The Cast API is also not fully
implemented and has some stubbed
methods. The current implementation
likely also has edge-cases and bugs
which may cause issues.
</p>
<p>
Check the
@@ -445,39 +471,40 @@
href="https://github.com/hensm/fx_cast-compat/issues?q=is%3Aissue+label%3Acompat"
>compatibility list</a
>
or if it's missing,
or if the site is not yet added,
<a
href="https://github.com/hensm/fx_cast-compat/issues/new/choose"
>submit a new compatibility report
issue</a
>submit a new compatibility
report issue</a
>.
</p>
</div>
</details>
</li>
<li class="faqs__list-item">
<details class="faq card">
<details class="faq">
<summary class="faq__summary">
<h3>
Why can't I cast DRM-encumbered media?
Why can't I cast DRM-encumbered
media?
</h3>
</summary>
<div class="faq__content">
<p>
Unforunately, for DRM-encumbered media,
there's no network-accessible URL to
provide to the Chromecast and no means
of accessing the media streams. The only
way to cast on sites like this is via
built-in Chromecast support (look for a
cast button), which may not always be
available.
Unforunately, for DRM-encumbered
media, there's no network-accessible
URL to provide to the Chromecast and
no means of accessing the media
streams. The only way to cast on
sites like this is via built-in
Chromecast support, which may not
always be available.
</p>
</div>
</details>
</li>
<li class="faqs__list-item">
<details class="faq card">
<details class="faq">
<summary class="faq__summary">
<h3>
Why is it taking so long for a full
@@ -486,25 +513,26 @@
</summary>
<div class="faq__content">
<p>
Though I do enjoy working on this, it's
(obviously) not a full-time thing. It's
just a hobby project. You can help speed
up development by contributing (see
below).
Though I do enjoy working on this,
it's (obviously) not a full-time
thing. It's just a hobby project.
You can help speed up development by
contributing (see below).
</p>
</div>
</details>
</li>
<li class="faqs__list-item">
<details class="faq card">
<details class="faq">
<summary class="faq__summary">
<h3>How can I support development?</h3>
</summary>
<div class="faq__content">
<p>
Contributing code, translations,
compatibility reports, or even reporting
bugs is very helpful. See the
compatibility reports, or even
reporting bugs is very helpful. See
the
<a
href="https://github.com/hensm/fx_cast/blob/master/CONTRIBUTING.md"
>contributing guide</a
@@ -527,76 +555,14 @@
</details>
</li>
</ul>
</div>
</section>
</main>
<picture style="display: contents">
<source
type="image/webp"
srcset="
images/webp/preview-bg.webp,
images/webp/preview-bg@2x.webp 2x
"
/>
<source
type="image/png"
srcset="images/preview-bg.png, images/preview-bg@2x.png 2x"
/>
<img
class="preview preview--bg"
alt="Screenshot preview (background), browser window."
src="images/preview-bg.png"
/>
</picture>
<picture style="display: contents">
<source
type="image/webp"
srcset="
images/webp/preview-fg_light.webp,
images/webp/preview-fg_light@2x.webp 2x
"
media="(prefers-color-scheme: light)"
/>
<source
type="image/webp"
srcset="
images/webp/preview-fg_dark.webp,
images/webp/preview-fg_dark@2x.webp 2x
"
media="(prefers-color-scheme: dark)"
/>
<source
type="image/png"
srcset="
images/preview-fg_light.png,
images/preview-fg_light@2x.png 2x
"
media="(prefers-color-scheme: light)"
/>
<source
type="image/png"
srcset="
images/preview-fg_dark.png,
images/preview-fg_dark@2x.png 2x
"
media="(prefers-color-scheme: dark)"
/>
<img
class="preview preview--fg"
alt="Screenshot preview (foreground), receiver selector popup."
width="462"
height="275"
src="images/preview-fg_dark.png"
/>
</picture>
<footer class="footer">
<div class="links">
<div class="page-width">
<a
class="links__link links__link-github"
class="github-link"
href="https://github.com/hensm/fx_cast"
title="Visit GitHub repository"
>

View File

@@ -1,9 +1,13 @@
/* eslint-env browser */
"use strict";
// Set FAQ fragment IDs
for (const faq of document.querySelectorAll(".faq")) {
const summary = faq.querySelector(".faq__summary");
const formattedSummary = summary.textContent.trim().replace(/ /g, "_");
const formattedSummary = summary.textContent
.replace(/\s\s+/g, " ")
.trim()
.replace(/ /g, "_");
faq.id = formattedSummary;
@@ -14,36 +18,33 @@ for (const faq of document.querySelectorAll(".faq")) {
}
}
function updateThemeClass(mediaQuery) {
if (mediaQuery.matches) {
document.documentElement.classList.remove("theme-dark");
document.documentElement.classList.add("theme-light");
} else {
document.documentElement.classList.remove("theme-light");
document.documentElement.classList.add("theme-dark");
window.addEventListener("hashchange", () => {
const targetElement = document.getElementById(
decodeURI(window.location.hash.slice(1))
);
if (targetElement && targetElement instanceof HTMLDetailsElement) {
targetElement.open = true;
}
}
const prefersLightScheme = window.matchMedia("(prefers-color-scheme: light)");
updateThemeClass(prefersLightScheme);
prefersLightScheme.addListener(updateThemeClass);
const downloadAppBtn = document.querySelector(".download__app");
const downloadAppOther = document.querySelector(".download__app-other");
const downloadAppOtherSummary =
downloadAppOther.querySelector(":scope > summary");
});
// Ext download button
const downloadExtBtn = document.querySelector(".download__ext");
// App download buttons
const appList = document.querySelector(".app-list");
const appListWin64Btn = document.querySelector(".app-list__win64");
const appListWin32Btn = document.querySelector(".app-list__win32");
const appListMacBtn = document.querySelector(".app-list__mac");
const appListDebBtn = document.querySelector(".app-list__deb");
const appListRpmBtn = document.querySelector(".app-list__rpm");
const downloadsBridgeAll = document.querySelector(".download__bridge-all");
const downloadsBridgeList = document.querySelector(".download__bridge-list");
const downloadsBridgePrimary = document.querySelector(
".download__bridge-primary"
);
const downloadsBridgeWin = document.createElement("div");
const downloadsBridgeMac = document.createElement("div");
const downloadsBridgeLinux = document.createElement("div");
downloadsBridgeList.append(
downloadsBridgeWin,
downloadsBridgeMac,
downloadsBridgeLinux
);
let platform;
@@ -51,148 +52,174 @@ switch (navigator.platform) {
case "Win32":
case "Win64":
platform = "win";
downloadAppBtn.textContent = "Windows Bridge";
appListWin64Btn.hidden = true;
break;
case "MacIntel":
platform = "mac";
downloadAppBtn.textContent = "macOS Bridge";
appListMacBtn.hidden = true;
break;
default:
/**
* Hide default download button and display other downloads
* without details summary.
*/
downloadAppBtn.remove();
downloadAppOther.open = true;
downloadAppOtherSummary.hidden = true;
appList.classList.add("app-list--buttons");
appListWin32Btn.classList.add("button");
appListWin64Btn.classList.add("button");
appListMacBtn.classList.add("button");
appListDebBtn.classList.add("button");
appListRpmBtn.classList.add("button");
}
function populateAppListApp(element, fileUrl, fileName, fileSize, version) {
element.href = fileUrl;
element.title = `${fileName} (${fileSize})`;
element.dataset.fileSize = fileSize;
element.dataset.version = version;
element.removeAttribute("disabled");
}
function addBridgeDownload(
tag,
version,
url,
title,
bridgePlatform,
linuxPackage
) {
const downloadButton = document.createElement("a");
downloadButton.classList.add("button", "button--puffy");
downloadButton.href = url;
downloadButton.title = title;
downloadButton.dataset.platform = linuxPackage ?? bridgePlatform;
const ENDPOINT_URL = "https://api.github.com/repos/hensm/fx_cast/releases";
const tagElement = document.createElement("span");
tagElement.classList.add("app-tag");
tagElement.textContent = tag;
fetch(ENDPOINT_URL)
.then(res => res.json())
.then(onResponse)
.catch(onError);
function onResponse(res) {
for (const release of res.reverse()) {
for (const asset of release.assets) {
const formattedSize = formatSize(asset.size);
const { tag_name } = release;
const REGEX_EXT = /.*\.(.*)$/;
const REGEX_ARCH = /.*(x(?:86|64))\..*$/;
switch (asset.name.match(REGEX_EXT).pop()) {
case "xpi":
downloadExtBtn.href = asset.browser_download_url;
downloadExtBtn.title = `${asset.name} (${formattedSize})`;
downloadExtBtn.dataset.version = tag_name;
downloadExtBtn.removeAttribute("disabled");
break;
case "exe":
switch (asset.name.match(REGEX_ARCH).pop()) {
case "x86":
populateAppListApp(
appListWin32Btn,
asset.browser_download_url,
asset.name,
formattedSize,
tag_name
);
break;
case "x64":
populateAppListApp(
appListWin64Btn,
asset.browser_download_url,
asset.name,
formattedSize,
tag_name
);
break;
}
break;
case "pkg":
populateAppListApp(
appListMacBtn,
asset.browser_download_url,
asset.name,
formattedSize,
tag_name
);
break;
case "deb":
populateAppListApp(
appListDebBtn,
asset.browser_download_url,
asset.name,
formattedSize,
tag_name
);
break;
case "rpm":
populateAppListApp(
appListRpmBtn,
asset.browser_download_url,
asset.name,
formattedSize,
tag_name
);
break;
}
}
}
if (platform) {
switch (platform) {
switch (bridgePlatform) {
case "win":
downloadAppBtn.href = appListWin64Btn.href;
downloadAppBtn.title = appListWin64Btn.title;
downloadAppBtn.dataset.version =
appListWin64Btn.dataset.version;
downloadButton.textContent = "Windows";
downloadsBridgeWin.append(downloadButton);
break;
case "mac":
downloadAppBtn.href = appListMacBtn.href;
downloadAppBtn.title = appListMacBtn.title;
downloadAppBtn.dataset.version = appListMacBtn.dataset.version;
downloadButton.textContent = "macOS";
downloadsBridgeMac.append(downloadButton);
break;
case "linux":
downloadButton.textContent = "Linux";
downloadsBridgeLinux.append(downloadButton);
break;
}
default: {
return;
if (bridgePlatform === platform) {
const primaryDownloadButton = downloadButton.cloneNode(true);
primaryDownloadButton.textContent += " Bridge";
primaryDownloadButton.append(tagElement.cloneNode(true));
primaryDownloadButton.classList.add("download__app");
downloadsBridgePrimary.append(primaryDownloadButton);
}
downloadButton.append(tagElement);
}
function populateDownloads(releaseList) {
let extensionUrl;
let extensionVersion;
let extensionTitle;
let bridgeVersion;
const bridgeAssets = [];
const PATTERN_FILE_EXT = /.*\.(.*)$/;
const PATTERN_ARCH = /.*(x86|x64|arm64)\..*$/;
for (const release of releaseList) {
const releaseBridgeAssets = [];
for (const asset of release.assets) {
const fileExtension = asset.name.match(PATTERN_FILE_EXT).pop();
if (fileExtension === "xpi") {
if (extensionUrl) break;
extensionUrl = asset.browser_download_url;
extensionVersion = release.tag_name;
extensionTitle = `${asset.name} (${formatSize(asset.size)})`;
} else {
switch (fileExtension) {
case "exe":
case "pkg":
case "deb":
case "rpm":
if (bridgeAssets.length) break;
releaseBridgeAssets.push(asset);
}
}
}
downloadAppBtn.removeAttribute("disabled");
if (releaseBridgeAssets.length) {
bridgeVersion = release.tag_name;
bridgeAssets.push(...releaseBridgeAssets);
}
}
downloadExtBtn.href = extensionUrl;
downloadExtBtn.title = extensionTitle;
downloadExtBtn.dataset.version = extensionVersion;
downloadExtBtn.removeAttribute("disabled");
for (const asset of bridgeAssets) {
const fileExtension = asset.name.match(PATTERN_FILE_EXT).pop();
const arch = asset.name.match(PATTERN_ARCH).pop();
const assetTitle = `${asset.name} (${formatSize(asset.size)})`;
let assetTag;
let assetPlatform;
switch (fileExtension) {
case "exe":
switch (arch) {
case "x64":
assetTag = "64-bit";
assetPlatform = "win";
break;
case "x86":
assetTag = "32-bit";
assetPlatform = "win";
break;
}
break;
case "pkg":
switch (arch) {
case "x64":
assetTag = "Intel";
assetPlatform = "mac";
break;
case "arm64":
assetTag = "ARM";
assetPlatform = "mac";
break;
}
break;
case "deb":
assetTag = "DEB";
assetPlatform = "linux";
break;
case "rpm":
assetTag = "RPM";
assetPlatform = "linux";
break;
}
addBridgeDownload(
assetTag,
bridgeVersion,
asset.browser_download_url,
assetTitle,
assetPlatform,
fileExtension === "deb" || fileExtension === "rpm"
? fileExtension
: undefined
);
}
if (!platform) {
downloadsBridgeAll.open = true;
}
}
function onError(err) {
console.error("Failed to fetch download links", err);
}
(async () => {
try {
populateDownloads(
await fetch(
"https://api.github.com/repos/hensm/fx_cast/releases"
).then(res => res.json())
);
} catch (err) {
console.error("Failed to fetch downloads!", err);
}
})();
function formatSize(bytes, precision = 1, useMetric = false) {
const factor = useMetric ? 1000 : 1024;
@@ -222,9 +249,5 @@ function formatSize(bytes, precision = 1, useMetric = false) {
return `${(bytes / txbyte).toFixed(precision)} ${
useMetric ? "TB" : "TiB"
}`;
} else if (bytes >= pxbyte) {
return `${(bytes / pxbyte).toFixed(precision)} ${
useMetric ? "PB" : "PiB"
}`;
}
}

View File

@@ -3,50 +3,30 @@
--shadow-20: 0 2px 8px rgba(12, 12, 13, 0.1);
--shadow-30: 0 4px 16px rgba(12, 12, 13, 0.1);
--__photon__focus_box-shadow:
0 0 0 1px #0a84ff inset
, 0 0 0 1px #0a84ff
, 0 0 0 4px rgba(10, 132, 255, 0.3);
--__photon__focus_box-shadow: 0 0 0 1px #0a84ff inset, 0 0 0 1px #0a84ff,
0 0 0 4px rgba(10, 132, 255, 0.3);
--__photon__link_color: var(--blue-60);
--__photon__link_color_hover: var(--blue-60);
--__photon__link_color_active: var(--blue-70);
--__photon__card_background: var(--white-100);
--__photon__card_border: 5px solid transparent;
--__photon__card_border-color_hover: var(--grey-30);
--__photon__card_border-radius: 4px;
--__photon__card_box-shadow: var(--shadow-10);
--__photon__button_background: var(--grey-90-a10);
--__photon__button_background_hover: var(--grey-90-a20);
--__photon__button_background_active: var(--grey-90-a30);
--__photon__button_background_primary: var(--blue-60);
--__photon__button_background_primary_hover: var(--blue-70);
--__photon__button_background_primary_active: var(--blue-80);
--__photon__button_background_ghost: transparent;
--__photon__button_background_ghost_hover: var(--grey-90-a10);
--__photon__button_background_ghost_active: var(--grey-90-a20);
--__photon__button_color: var(--grey-90);
--__photon__button_color_primary: var(--white-100);
--__photon__button_color_ghost: var(--grey-90-a80);
}
:root.theme-dark {
--__photon__link_color: var(--blue-50);
--__photon__link_color_hover: var(--blue-50);
--__photon__link_color_active: var(--blue-60);
--__photon__card_background: #202023;
--__photon__card_border: 5px solid transparent;
--__photon__card_border-color_hover: var(--grey-60);
--__photon__card_border-radius: 4px;
--__photon__card_box-shadow: var(--shadow-10);
--__photon__button_background: var(--grey-10-a10);
--__photon__button_background_hover: rgba(249, 249, 250, 0.15);
--__photon__button_background_active: rgba(249, 249, 250, 0.2);
--__photon__button_background_primary: var(--blue-60);
--__photon__button_background_primary_hover: var(--blue-70);
--__photon__button_background_primary_active: var(--blue-80);
--__photon__button_background_ghost: transparent;
--__photon__button_background_ghost_hover: rgba(249, 249, 250, 0.1);
--__photon__button_background_ghost_active: rgba(249, 249, 250, 0.15);
--__photon__button_color: var(--white-100);
--__photon__button_color_primary: var(--white-100);
--__photon__button_color_ghost: var(--grey-10-a80);
}
@@ -65,7 +45,7 @@ a:not(.button):hover {
a:not(.button):hover:active {
color: var(--__photon__link_color_active);
}
a:not(.button):focus {
a:not(.button):focus-visible {
box-shadow: var(--__photon__focus_box-shadow);
}
@@ -85,7 +65,6 @@ a:not(.button):focus {
border-color: var(--__photon__card_border-color_hover);
}
/* ------------------------ */
/* -------- Buttons ------- */
/* ------------------------ */
@@ -143,21 +122,16 @@ a:not(.button):focus {
padding: 0 16px;
}
.button:not(
.button--micro):not(
.button--puffy):not(
.button--ghost) {
.button:not(.button--micro):not(.button--puffy):not(.button--ghost) {
min-width: 132px;
}
/* Behaviours */
.button:disabled,
.button[disabled] {
opacity: 0.4;
}
.button:focus,
.button:focus-within {
.button:focus-visible {
box-shadow: var(--__photon__focus_box-shadow);
}
.button::-moz-focus-inner {
@@ -191,20 +165,19 @@ a:not(.button):focus {
background-color: var(--__photon__button_background_ghost_active);
}
/* ------------------------ */
/* ------ Typography ------ */
/* ------------------------ */
.display {}
.display {
}
.display--20 {
font-size: 36px;
font-weight: 200;
}
.title {}
.title {
}
.title--40,
.title--30 {
font-weight: 300;
@@ -215,19 +188,35 @@ a:not(.button):focus {
font-weight: 500;
}
.title--40 { font-size: 28px; }
.title--30 { font-size: 22px; }
.title--20 { font-size: 17px; }
.title--10 { font-size: 13px; }
.title--40 {
font-size: 28px;
}
.title--30 {
font-size: 22px;
}
.title--20 {
font-size: 17px;
}
.title--10 {
font-size: 13px;
}
.body {
font-weight: 400;
}
.body > em {
font-weight: 700;
}
.body { font-weight: 400; }
.body > em { font-weight: 700; }
.body--30 { font-size: 17px; }
.body--20 { font-size: 15px; }
.body--10 { font-size: 13px; }
.body--30 {
font-size: 17px;
}
.body--20 {
font-size: 15px;
}
.body--10 {
font-size: 13px;
}
.caption {
color: GrayText;
@@ -237,7 +226,12 @@ a:not(.button):focus {
font-weight: 700;
}
.caption--30 { font-size: 15px; }
.caption--20 { font-size: 13px; }
.caption--10 { font-size: 11px; }
.caption--30 {
font-size: 15px;
}
.caption--20 {
font-size: 13px;
}
.caption--10 {
font-size: 11px;
}