Update site design/text to match new version
4
docs/icons/apple.svg
Normal 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 |
@@ -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 |
@@ -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 |
@@ -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
@@ -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 |
6
docs/icons/photon_info.svg
Normal 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 |
6
docs/icons/photon_warning.svg
Normal 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
@@ -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
@@ -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
|
After Width: | Height: | Size: 70 KiB |
BIN
docs/images/menu.webp
Normal file
|
After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 139 KiB |
|
Before Width: | Height: | Size: 388 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 90 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 91 KiB |
BIN
docs/images/preview.png
Normal file
|
After Width: | Height: | Size: 157 KiB |
BIN
docs/images/preview.webp
Normal file
|
After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 114 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 49 KiB |
421
docs/index.css
@@ -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 {
|
||||||
|
|||||||
560
docs/index.html
@@ -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"
|
||||||
>
|
>
|
||||||
|
|||||||
327
docs/index.js
@@ -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"
|
|
||||||
}`;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
112
docs/photon.css
@@ -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;
|
||||||
|
}
|
||||||
|
|||||||