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

View File

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

View File

@@ -1,9 +1,13 @@
/* eslint-env browser */
"use strict"; "use strict";
// Set FAQ fragment IDs // Set FAQ fragment IDs
for (const faq of document.querySelectorAll(".faq")) { for (const faq of document.querySelectorAll(".faq")) {
const summary = faq.querySelector(".faq__summary"); 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; faq.id = formattedSummary;
@@ -14,36 +18,33 @@ for (const faq of document.querySelectorAll(".faq")) {
} }
} }
function updateThemeClass(mediaQuery) { window.addEventListener("hashchange", () => {
if (mediaQuery.matches) { const targetElement = document.getElementById(
document.documentElement.classList.remove("theme-dark"); decodeURI(window.location.hash.slice(1))
document.documentElement.classList.add("theme-light"); );
} else { if (targetElement && targetElement instanceof HTMLDetailsElement) {
document.documentElement.classList.remove("theme-light"); targetElement.open = true;
document.documentElement.classList.add("theme-dark");
} }
} });
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 // Ext download button
const downloadExtBtn = document.querySelector(".download__ext"); const downloadExtBtn = document.querySelector(".download__ext");
// App download buttons const downloadsBridgeAll = document.querySelector(".download__bridge-all");
const appList = document.querySelector(".app-list"); const downloadsBridgeList = document.querySelector(".download__bridge-list");
const appListWin64Btn = document.querySelector(".app-list__win64"); const downloadsBridgePrimary = document.querySelector(
const appListWin32Btn = document.querySelector(".app-list__win32"); ".download__bridge-primary"
const appListMacBtn = document.querySelector(".app-list__mac"); );
const appListDebBtn = document.querySelector(".app-list__deb");
const appListRpmBtn = document.querySelector(".app-list__rpm"); const downloadsBridgeWin = document.createElement("div");
const downloadsBridgeMac = document.createElement("div");
const downloadsBridgeLinux = document.createElement("div");
downloadsBridgeList.append(
downloadsBridgeWin,
downloadsBridgeMac,
downloadsBridgeLinux
);
let platform; let platform;
@@ -51,148 +52,174 @@ switch (navigator.platform) {
case "Win32": case "Win32":
case "Win64": case "Win64":
platform = "win"; platform = "win";
downloadAppBtn.textContent = "Windows Bridge";
appListWin64Btn.hidden = true;
break; break;
case "MacIntel": case "MacIntel":
platform = "mac"; platform = "mac";
downloadAppBtn.textContent = "macOS Bridge";
appListMacBtn.hidden = true;
break; 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) { function addBridgeDownload(
element.href = fileUrl; tag,
element.title = `${fileName} (${fileSize})`; version,
element.dataset.fileSize = fileSize; url,
element.dataset.version = version; title,
element.removeAttribute("disabled"); 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) switch (bridgePlatform) {
.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) {
case "win": case "win":
downloadAppBtn.href = appListWin64Btn.href; downloadButton.textContent = "Windows";
downloadAppBtn.title = appListWin64Btn.title; downloadsBridgeWin.append(downloadButton);
downloadAppBtn.dataset.version =
appListWin64Btn.dataset.version;
break; break;
case "mac": case "mac":
downloadAppBtn.href = appListMacBtn.href; downloadButton.textContent = "macOS";
downloadAppBtn.title = appListMacBtn.title; downloadsBridgeMac.append(downloadButton);
downloadAppBtn.dataset.version = appListMacBtn.dataset.version;
break; break;
case "linux":
downloadButton.textContent = "Linux";
downloadsBridgeLinux.append(downloadButton);
break;
}
default: { if (bridgePlatform === platform) {
return; 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) { (async () => {
console.error("Failed to fetch download links", err); 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) { function formatSize(bytes, precision = 1, useMetric = false) {
const factor = useMetric ? 1000 : 1024; const factor = useMetric ? 1000 : 1024;
@@ -222,9 +249,5 @@ function formatSize(bytes, precision = 1, useMetric = false) {
return `${(bytes / txbyte).toFixed(precision)} ${ return `${(bytes / txbyte).toFixed(precision)} ${
useMetric ? "TB" : "TiB" 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-20: 0 2px 8px rgba(12, 12, 13, 0.1);
--shadow-30: 0 4px 16px rgba(12, 12, 13, 0.1); --shadow-30: 0 4px 16px rgba(12, 12, 13, 0.1);
--__photon__focus_box-shadow: --__photon__focus_box-shadow: 0 0 0 1px #0a84ff inset, 0 0 0 1px #0a84ff,
0 0 0 1px #0a84ff inset 0 0 0 4px rgba(10, 132, 255, 0.3);
, 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: var(--blue-50);
--__photon__link_color_hover: var(--blue-50); --__photon__link_color_hover: var(--blue-50);
--__photon__link_color_active: var(--blue-60); --__photon__link_color_active: var(--blue-60);
--__photon__card_background: #202023; --__photon__card_background: #202023;
--__photon__card_border: 5px solid transparent;
--__photon__card_border-color_hover: var(--grey-60); --__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: var(--grey-10-a10);
--__photon__button_background_hover: rgba(249, 249, 250, 0.15); --__photon__button_background_hover: rgba(249, 249, 250, 0.15);
--__photon__button_background_active: rgba(249, 249, 250, 0.2); --__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_hover: rgba(249, 249, 250, 0.1);
--__photon__button_background_ghost_active: rgba(249, 249, 250, 0.15); --__photon__button_background_ghost_active: rgba(249, 249, 250, 0.15);
--__photon__button_color: var(--white-100); --__photon__button_color: var(--white-100);
--__photon__button_color_primary: var(--white-100);
--__photon__button_color_ghost: var(--grey-10-a80); --__photon__button_color_ghost: var(--grey-10-a80);
} }
@@ -65,7 +45,7 @@ a:not(.button):hover {
a:not(.button):hover:active { a:not(.button):hover:active {
color: var(--__photon__link_color_active); color: var(--__photon__link_color_active);
} }
a:not(.button):focus { a:not(.button):focus-visible {
box-shadow: var(--__photon__focus_box-shadow); box-shadow: var(--__photon__focus_box-shadow);
} }
@@ -85,7 +65,6 @@ a:not(.button):focus {
border-color: var(--__photon__card_border-color_hover); border-color: var(--__photon__card_border-color_hover);
} }
/* ------------------------ */ /* ------------------------ */
/* -------- Buttons ------- */ /* -------- Buttons ------- */
/* ------------------------ */ /* ------------------------ */
@@ -143,21 +122,16 @@ a:not(.button):focus {
padding: 0 16px; padding: 0 16px;
} }
.button:not( .button:not(.button--micro):not(.button--puffy):not(.button--ghost) {
.button--micro):not(
.button--puffy):not(
.button--ghost) {
min-width: 132px; min-width: 132px;
} }
/* Behaviours */ /* Behaviours */
.button:disabled, .button:disabled,
.button[disabled] { .button[disabled] {
opacity: 0.4; opacity: 0.4;
} }
.button:focus, .button:focus-visible {
.button:focus-within {
box-shadow: var(--__photon__focus_box-shadow); box-shadow: var(--__photon__focus_box-shadow);
} }
.button::-moz-focus-inner { .button::-moz-focus-inner {
@@ -191,20 +165,19 @@ a:not(.button):focus {
background-color: var(--__photon__button_background_ghost_active); background-color: var(--__photon__button_background_ghost_active);
} }
/* ------------------------ */ /* ------------------------ */
/* ------ Typography ------ */ /* ------ Typography ------ */
/* ------------------------ */ /* ------------------------ */
.display {} .display {
}
.display--20 { .display--20 {
font-size: 36px; font-size: 36px;
font-weight: 200; font-weight: 200;
} }
.title {
.title {} }
.title--40, .title--40,
.title--30 { .title--30 {
font-weight: 300; font-weight: 300;
@@ -215,19 +188,35 @@ a:not(.button):focus {
font-weight: 500; font-weight: 500;
} }
.title--40 { font-size: 28px; } .title--40 {
.title--30 { font-size: 22px; } font-size: 28px;
.title--20 { font-size: 17px; } }
.title--10 { font-size: 13px; } .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--30 {
.body > em { font-weight: 700; } font-size: 17px;
}
.body--30 { font-size: 17px; } .body--20 {
.body--20 { font-size: 15px; } font-size: 15px;
.body--10 { font-size: 13px; } }
.body--10 {
font-size: 13px;
}
.caption { .caption {
color: GrayText; color: GrayText;
@@ -237,7 +226,12 @@ a:not(.button):focus {
font-weight: 700; font-weight: 700;
} }
.caption--30 { font-size: 15px; } .caption--30 {
.caption--20 { font-size: 13px; } font-size: 15px;
.caption--10 { font-size: 11px; } }
.caption--20 {
font-size: 13px;
}
.caption--10 {
font-size: 11px;
}