Compare commits
163 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
fb1575d875 | ||
![]() |
004b946716 | ||
![]() |
6400722712 | ||
![]() |
d9ec28459e | ||
![]() |
407c1d24af | ||
![]() |
de6d8d1153 | ||
![]() |
3eb10fc05b | ||
![]() |
1ab6f77f95 | ||
![]() |
c1b15b59db | ||
![]() |
3dae5a6d47 | ||
![]() |
dab2646054 | ||
![]() |
ad0485d651 | ||
![]() |
46bbbccdc9 | ||
![]() |
ee28417a4c | ||
![]() |
746ac1eec7 | ||
![]() |
8b67c4fdd1 | ||
![]() |
c3e658d46a | ||
![]() |
ebded1a73b | ||
![]() |
cf879a5c23 | ||
![]() |
4aa3e5b34d | ||
![]() |
303e6066e2 | ||
![]() |
861cd15240 | ||
![]() |
d695ddb91a | ||
![]() |
7abb2edb2f | ||
![]() |
dfe8abd496 | ||
![]() |
61b384ee56 | ||
![]() |
d71a890430 | ||
![]() |
2c85a85fff | ||
![]() |
ce6074530f | ||
![]() |
e20228153c | ||
![]() |
e431170435 | ||
![]() |
c671d1e389 | ||
![]() |
31a5e70b26 | ||
![]() |
0c68c72b29 | ||
![]() |
2b158fdf57 | ||
![]() |
dd005b31a4 | ||
![]() |
0b467cc149 | ||
![]() |
46e2fdca00 | ||
![]() |
983b06266b | ||
![]() |
cb8708d2d9 | ||
![]() |
adbec11c04 | ||
![]() |
404f00c02b | ||
![]() |
5d346205fc | ||
![]() |
db3f1a7c09 | ||
![]() |
d2599f1f9a | ||
![]() |
ed88aafdc1 | ||
![]() |
d94deed341 | ||
![]() |
4b49d87a81 | ||
![]() |
4a6281ebf6 | ||
![]() |
332443fe81 | ||
![]() |
96c784704a | ||
![]() |
b0d10919d7 | ||
![]() |
b0e4681b5f | ||
![]() |
2958f6ea7f | ||
![]() |
4d46f94975 | ||
![]() |
4cc7e9ca98 | ||
![]() |
7688a11ef9 | ||
![]() |
80b182cc54 | ||
![]() |
b6936e7ca4 | ||
![]() |
1590326fc1 | ||
![]() |
1a1eb3264f | ||
![]() |
3d80a8aa39 | ||
![]() |
6cca084e05 | ||
![]() |
1c2c496f7e | ||
![]() |
8ab60be68b | ||
![]() |
f1fe363083 | ||
![]() |
db619790be | ||
![]() |
608749ce1a | ||
![]() |
1135744520 | ||
![]() |
c8d616e657 | ||
![]() |
3f8a6e04c8 | ||
![]() |
851cd8e037 | ||
![]() |
7b3dae8bea | ||
![]() |
e04ec0a00b | ||
![]() |
0a61c26cc1 | ||
![]() |
ff35c58787 | ||
![]() |
0a464fa93a | ||
![]() |
a9958e88d0 | ||
![]() |
d3eb5907a4 | ||
![]() |
a2017cc4c7 | ||
![]() |
87124fdaf4 | ||
![]() |
394c2b54ce | ||
![]() |
7117f1ad62 | ||
![]() |
713e267c16 | ||
![]() |
3932ec21f5 | ||
![]() |
76dc50b052 | ||
![]() |
73749aa34c | ||
![]() |
897932f954 | ||
![]() |
5a2b469e8a | ||
![]() |
ad38e6c15e | ||
![]() |
f5c6fc13a8 | ||
![]() |
7c8625821a | ||
![]() |
8a696ad088 | ||
![]() |
3c1ca8b70f | ||
![]() |
87b0cee53a | ||
![]() |
a56aa7e308 | ||
![]() |
98220c5e74 | ||
![]() |
964c886fb6 | ||
![]() |
f6536aa1d2 | ||
![]() |
ec1c861b13 | ||
![]() |
ae07ed9445 | ||
![]() |
82b94db408 | ||
![]() |
54d716e4b6 | ||
![]() |
a0330465dd | ||
![]() |
af026cfe66 | ||
![]() |
b7d5f6655d | ||
![]() |
964dedba0f | ||
![]() |
f13537e812 | ||
![]() |
037f1bf09f | ||
![]() |
9ee4212060 | ||
![]() |
e3c60cb4d8 | ||
![]() |
6fa325065e | ||
![]() |
cc88c99c45 | ||
![]() |
9d36ed6b1b | ||
![]() |
a6b8843c5c | ||
![]() |
9cf4dbd710 | ||
![]() |
589335f665 | ||
![]() |
1a04cac47c | ||
![]() |
417c6d09bf | ||
![]() |
c36cb4a76a | ||
![]() |
e65b786b46 | ||
![]() |
713f1486c3 | ||
![]() |
a0d3447202 | ||
![]() |
286999599a | ||
![]() |
9b6fae2523 | ||
![]() |
c250279b46 | ||
![]() |
f687df335e | ||
![]() |
aeec7866b4 | ||
![]() |
b49c47516e | ||
![]() |
3bf854c6c3 | ||
![]() |
b55edb8ae9 | ||
![]() |
78bc66668c | ||
![]() |
f965abe7f1 | ||
![]() |
509cb2471d | ||
![]() |
3c273d817b | ||
![]() |
21817ca97a | ||
![]() |
b31e712d2c | ||
![]() |
8f1ee11ff2 | ||
![]() |
0cb80ace3f | ||
![]() |
295a2bb8b8 | ||
![]() |
dd6757be5b | ||
![]() |
e90e4b27a3 | ||
![]() |
2932ca6c2b | ||
![]() |
06a685fc31 | ||
![]() |
e06c20d2f6 | ||
![]() |
e5527cf825 | ||
![]() |
6864af1b2f | ||
![]() |
87ff59bfa7 | ||
![]() |
ecd407d924 | ||
![]() |
ce55e7eed5 | ||
![]() |
f9b3fed403 | ||
![]() |
484f77bffc | ||
![]() |
814e697675 | ||
![]() |
e469c04125 | ||
![]() |
a33e2cbd88 | ||
![]() |
4ecccd67bd | ||
![]() |
8af25b4c67 | ||
![]() |
d6c30caf1b | ||
![]() |
7025efa6f8 | ||
![]() |
d0877eb6bc | ||
![]() |
87c62b4319 | ||
![]() |
9d3382d773 | ||
![]() |
5333e92c42 |
20
.formal-git/components
Normal file
@@ -0,0 +1,20 @@
|
||||
split-view
|
||||
kbs
|
||||
folders
|
||||
workspaces
|
||||
mods
|
||||
tests
|
||||
glance
|
||||
media
|
||||
images
|
||||
vendor
|
||||
tabs
|
||||
compact-mode
|
||||
common
|
||||
fonts
|
||||
welcome
|
||||
scripts
|
||||
workflows
|
||||
winsign
|
||||
flatpak
|
||||
configs
|
1
.formal-git/template
Normal file
@@ -0,0 +1 @@
|
||||
{type}: {message}, b=({bugId}), c={components}
|
2
.github/workflows/build.yml
vendored
@@ -503,7 +503,7 @@ jobs:
|
||||
- name: Download object files
|
||||
if: ${{ inputs.update_branch == 'release' }}
|
||||
run: |
|
||||
git clone https://github.com/zen-browser/windows-binaries.git .github/workflows/object
|
||||
git clone https://github.com/zen-browser/windows-binaries.git .github/workflows/object --depth 1
|
||||
|
||||
- name: Copy update manifests
|
||||
env:
|
||||
|
2
.github/workflows/code-linter.yml
vendored
@@ -11,7 +11,7 @@ on:
|
||||
- dev
|
||||
|
||||
jobs:
|
||||
pr-test:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
|
@@ -14,7 +14,7 @@ on:
|
||||
description: 'Use sccache'
|
||||
required: false
|
||||
type: boolean
|
||||
default: true
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
twilight-release-schedule:
|
||||
|
22
.github/workflows/windows-release-build.yml
vendored
@@ -111,6 +111,7 @@ jobs:
|
||||
set -x
|
||||
mkdir -p ~/win-cross
|
||||
cd engine/
|
||||
sudo apt-get install python3-launchpadlib
|
||||
sudo add-apt-repository ppa:savoury1/backports
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y python3-pip autoconf \
|
||||
@@ -280,21 +281,24 @@ jobs:
|
||||
if: ${{ !inputs.generate-gpo }}
|
||||
run: |
|
||||
set -x
|
||||
if test "${{ matrix.arch }}" = "aarch64"; then
|
||||
find engine/obj-aarch64-pc-windows-msvc/ -mindepth 1 -maxdepth 1 -type d -not -name 'dist' -exec rm -rf {} \;
|
||||
find engine/obj-aarch64-pc-windows-msvc/ -mindepth 1 -maxdepth 1 -type f -not -name 'dist' -exec rm -f {} \;
|
||||
else
|
||||
find engine/obj-x86_64-pc-windows-msvc/ -mindepth 1 -maxdepth 1 -type d -not -name 'dist' -exec rm -rf {} \;
|
||||
find engine/obj-x86_64-pc-windows-msvc/ -mindepth 1 -maxdepth 1 -type f -not -name 'dist' -exec rm -f {} \;
|
||||
fi
|
||||
mkdir obj-${{ matrix.arch }}-pc-windows-msvc/
|
||||
|
||||
rm -rf engine/obj-${{ matrix.arch }}-pc-windows-msvc/_tests
|
||||
rm -rf engine/obj-${{ matrix.arch }}-pc-windows-msvc/config/autoconf.mk
|
||||
rm -rf engine/obj-${{ matrix.arch }}-pc-windows-msvc/config.statusd/substs/
|
||||
rm -rf engine/obj-${{ matrix.arch }}-pc-windows-msvc/dist/install
|
||||
|
||||
find engine/obj-${{ matrix.arch }}-pc-windows-msvc/dist -maxdepth 1 -type f -name "*.zip" -delete
|
||||
|
||||
cp -r --no-dereference engine/obj-${{ matrix.arch }}-pc-windows-msvc/* obj-${{ matrix.arch }}-pc-windows-msvc/ || true
|
||||
|
||||
- name: Upload dist object
|
||||
if: ${{ !inputs.generate-gpo }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
retention-days: 5
|
||||
retention-days: 2
|
||||
name: windows-x64-obj-${{ matrix.arch == 'aarch64' && 'arm64' || matrix.arch }}
|
||||
path: engine/obj-${{ matrix.arch == 'aarch64' && 'aarch64' || 'x86_64' }}-pc-windows-msvc/
|
||||
path: obj-${{ matrix.arch }}-pc-windows-msvc
|
||||
|
||||
- name: Upload artifact (if Twilight branch, binary)
|
||||
if: ${{ inputs.release-branch == 'twilight' && !inputs.generate-gpo }}
|
||||
|
1
.gitignore
vendored
@@ -11,3 +11,4 @@ windsign-temp/
|
||||
venv/
|
||||
|
||||
!firefox-cache/
|
||||
win-cross/
|
||||
|
@@ -22,9 +22,8 @@ docs/issue-metrics/*.md
|
||||
|
||||
# Some CSS files are preprocessed and prettier doesn't handle them well
|
||||
# We also dont want to format the CSS files that are generated by the build
|
||||
src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css
|
||||
src/browser/base/content/zen-styles/zen-compact-mode.css
|
||||
src/browser/base/zen-components/ZenEmojies.mjs
|
||||
build/codesign/codesign.bash
|
||||
src/zen/tabs/zen-tabs/vertical-tabs.css
|
||||
src/zen/compact-mode/zen-compact-mode.css
|
||||
src/zen/common/ZenEmojies.mjs
|
||||
|
||||
*.inc
|
||||
|
10
README.md
@@ -28,9 +28,9 @@
|
||||
|
||||
## 🖥️ Compatibility
|
||||
|
||||
Zen is currently built using Firefox version `136.0.2`! 🚀
|
||||
Zen is currently built using Firefox version `137.0.2`! 🚀
|
||||
|
||||
- [`Zen Twilight`](https://zen-browser.app/download?twilight) - Is currently built using Firefox version `RC 136.0`!
|
||||
- [`Zen Twilight`](https://zen-browser.app/download?twilight) - Is currently built using Firefox version `RC 137.0.2`!
|
||||
- Check out the latest [release notes](https://zen-browser.app/release-notes)!
|
||||
- Part of our mission is to keep Zen up-to-date with the latest version of Firefox, so you can enjoy the latest features and security updates!
|
||||
|
||||
@@ -85,7 +85,7 @@ winget install --id Zen-Team.Zen-Browser
|
||||
You can also install Zen using Homebrew:
|
||||
|
||||
```
|
||||
brew install --cask zen-browser
|
||||
brew install zen-browser
|
||||
```
|
||||
|
||||
#### Linux
|
||||
@@ -118,11 +118,11 @@ To upgrade the browser to a newer version, use the embedded update functionality
|
||||
|
||||
## 👨💻 Development and Contributing
|
||||
|
||||
Some components used by @zen-browser as an attempt to make firefox forks a better place, and for other to enjoy the beauty of OSS. You can find them [here](https://github.com/zen-browser/desktop/tree/dev/src/browser/base/zen-components).
|
||||
Some components used by @zen-browser as an attempt to make firefox forks a better place, and for other to enjoy the beauty of OSS. You can find them [here](https://github.com/zen-browser/desktop/tree/dev/src/zen).
|
||||
|
||||
#### `Run Locally`
|
||||
|
||||
In order to download and run Zen locally, please follow [these instructions](https://docs.zen-browser.app/building).
|
||||
In order to download and run Zen locally, please follow [these instructions](https://docs.zen-browser.app/guides/building).
|
||||
|
||||
#### `Special Thanks`
|
||||
|
||||
|
@@ -1 +1 @@
|
||||
e834aca3620253ea774e85826e43dd55e0c4f8b2
|
||||
ee85441427e22eb9fbc8d3eb62c7e5804535f0bc
|
@@ -49,6 +49,12 @@ modules:
|
||||
strip-components: 0
|
||||
only-arches:
|
||||
- x86_64
|
||||
x-checker-data:
|
||||
type: json
|
||||
url: https://api.github.com/repos/zen-browser/desktop/releases/latest
|
||||
version-query: .tag_name
|
||||
url-query: .assets[] | select(.name=="zen.linux-x86_64.tar.xz") | .browser_download_url
|
||||
is-main-source: true
|
||||
|
||||
- type: archive
|
||||
url: https://github.com/zen-browser/desktop/releases/download/{version}/zen.linux-aarch64.tar.xz
|
||||
@@ -56,6 +62,12 @@ modules:
|
||||
strip-components: 0
|
||||
only-arches:
|
||||
- aarch64
|
||||
x-checker-data:
|
||||
type: json
|
||||
url: https://api.github.com/repos/zen-browser/desktop/releases/latest
|
||||
version-query: .tag_name
|
||||
url-query: .assets[] | select(.name=="zen.linux-aarch64.tar.xz") | .browser_download_url
|
||||
is-main-source: true
|
||||
|
||||
- type: archive
|
||||
url: https://github.com/zen-browser/flatpak/releases/download/{version}/archive.tar
|
||||
|
9
build/winsign/bootstrap.ps1
Normal file
@@ -0,0 +1,9 @@
|
||||
(New-Object System.Net.WebClient).DownloadFile("https://ftp.mozilla.org/pub/mozilla/libraries/win32/MozillaBuildSetup-Latest.exe", "C:\MozillaBuildSetup-Latest.exe")
|
||||
C:\MozillaBuildSetup-Latest.exe /S | out-null
|
||||
|
||||
rustup target add aarch64-pc-windows-msvc
|
||||
rustup target add x86_64-pc-windows-msvc
|
||||
|
||||
cd engine
|
||||
./mach python --virtualenv build taskcluster/scripts/misc/get_vs.py build/vs/vs2022.yaml ../win-cross/vs2022
|
||||
cd ..
|
@@ -6,7 +6,7 @@ param(
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
echo "Preparing environment"
|
||||
git pull --recurse-submodules
|
||||
git pull --recurse
|
||||
mkdir windsign-temp -ErrorAction SilentlyContinue
|
||||
|
||||
# Download in parallel
|
||||
@@ -19,40 +19,145 @@ mkdir windsign-temp -ErrorAction SilentlyContinue
|
||||
# echo "Downloaded git objects repo to"
|
||||
#} -Verbose -ArgumentList $PWD -Debug
|
||||
|
||||
gh run download $GithubRunId --name windows-x64-obj-arm64 -D windsign-temp\windows-x64-obj-arm64
|
||||
echo "Downloaded arm64 artifacts"
|
||||
gh run download $GithubRunId --name windows-x64-obj-x86_64 -D windsign-temp\windows-x64-obj-x86_64
|
||||
echo "Downloaded x86_64 artifacts"
|
||||
Start-Job -Name "DownloadGitl10n" -ScriptBlock {
|
||||
param($PWD)
|
||||
cd $PWD
|
||||
$env:ZEN_L10N_CURR_DIR=[regex]::replace($PWD, "^([A-Z]):", { "/" + $args.value.Substring(0, 1).toLower() }) -replace "\\", "/"
|
||||
C:\mozilla-build\start-shell.bat $PWD\scripts\download-language-packs.sh
|
||||
echo "Fetched l10n and firefox's one"
|
||||
} -Verbose -ArgumentList $PWD -Debug
|
||||
|
||||
Start-Job -Name "SurferInit" -ScriptBlock {
|
||||
param($PWD)
|
||||
cd $PWD
|
||||
surfer -- ci --brand release
|
||||
npm run import -- --verbose
|
||||
} -Verbose -ArgumentList $PWD -Debug
|
||||
|
||||
#Wait-Job -Name "DownloadGitObjectsRepo"
|
||||
echo "Downloading artifacts info"
|
||||
$artifactsInfo=gh api repos/zen-browser/desktop/actions/runs/$GithubRunId/artifacts
|
||||
$token = gh auth token
|
||||
|
||||
function New-TemporaryDirectory {
|
||||
$tmp = [System.IO.Path]::GetTempPath() # Not $env:TEMP, see https://stackoverflow.com/a/946017
|
||||
$name = (New-Guid).ToString("N")
|
||||
New-Item -ItemType Directory -Path (Join-Path $tmp $name)
|
||||
}
|
||||
|
||||
function DownloadFile($url, $targetFile) {
|
||||
$uri = New-Object "System.Uri" "$url"
|
||||
$request = [System.Net.HttpWebRequest]::Create($uri)
|
||||
$request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3"
|
||||
$request.Headers.Add("Authorization", "Bearer $token")
|
||||
$response = $request.GetResponse()
|
||||
$totalLength = [System.Math]::Floor($response.get_ContentLength()/1024)
|
||||
$responseStream = $response.GetResponseStream()
|
||||
$targetStream = New-Object -TypeName System.IO.FileStream -ArgumentList $targetFile, Create
|
||||
$buffer = new-object byte[] 10KB
|
||||
$count = $responseStream.Read($buffer,0,$buffer.length)
|
||||
$downloadedBytes = $count
|
||||
|
||||
while ($count -gt 0) {
|
||||
$targetStream.Write($buffer, 0, $count)
|
||||
$count = $responseStream.Read($buffer,0,$buffer.length)
|
||||
$downloadedBytes = $downloadedBytes + $count
|
||||
Write-Progress -activity "Downloading file '$($url.split('/') | Select -Last 1)'" -status "Downloaded ($([System.Math]::Floor($downloadedBytes/1024))K of $($totalLength)K): " -PercentComplete ((([System.Math]::Floor($downloadedBytes/1024)) / $totalLength) * 100)
|
||||
}
|
||||
|
||||
Write-Progress -activity "Finished downloading file '$($url.split('/') | Select -Last 1)'"
|
||||
|
||||
$targetStream.Flush()
|
||||
$targetStream.Close()
|
||||
$targetStream.Dispose()
|
||||
$responseStream.Dispose()
|
||||
}
|
||||
|
||||
function DownloadArtifacts($name) {
|
||||
echo "Downloading artifacts for $name"
|
||||
$artifactUrl=$($artifactsInfo | jq -r --arg NAME "windows-x64-obj-$name" '.artifacts[] | select(.name == $NAME) | .archive_download_url')
|
||||
echo "Artifact URL: $artifactUrl"
|
||||
|
||||
# download the artifact
|
||||
$outputPath="$PWD\windsign-temp\windows-x64-obj-$name"
|
||||
$tempDir = New-TemporaryDirectory
|
||||
$tempFile = Join-Path $tempDir "artifact-$($name).zip"
|
||||
|
||||
echo "Downloading artifact to $tempFile"
|
||||
DownloadFile $artifactUrl $tempFile
|
||||
|
||||
Start-Job -Name "UnzipArtifact$name" -ScriptBlock {
|
||||
param($tempFile, $outputPath)
|
||||
echo "Unzipping artifact to $outputPath"
|
||||
Expand-Archive -Path $tempFile -DestinationPath $outputPath -Force
|
||||
echo "Unzipped artifact to $outputPath"
|
||||
} -ArgumentList $tempFile, $outputPath -Verbose -Debug
|
||||
}
|
||||
|
||||
DownloadArtifacts arm64
|
||||
DownloadArtifacts x86_64
|
||||
|
||||
# Wait for the jobs to finish
|
||||
Wait-Job -Name "UnzipArtifactarm64"
|
||||
Wait-Job -Name "UnzipArtifactx86_64"
|
||||
|
||||
mkdir engine\obj-x86_64-pc-windows-msvc\ -ErrorAction SilentlyContinue
|
||||
|
||||
npm run surfer -- ci --brand release
|
||||
# Collect all .exe and .dll files into a list
|
||||
$files = Get-ChildItem windsign-temp\windows-x64-obj-x86_64\ -Recurse -Include *.exe
|
||||
$files += Get-ChildItem windsign-temp\windows-x64-obj-x86_64\ -Recurse -Include *.dll
|
||||
|
||||
$files += Get-ChildItem windsign-temp\windows-x64-obj-arm64\ -Recurse -Include *.exe
|
||||
$files += Get-ChildItem windsign-temp\windows-x64-obj-arm64\ -Recurse -Include *.dll
|
||||
|
||||
signtool.exe sign /n "$SignIdentity" /t http://time.certum.pl/ /fd sha256 /v $files
|
||||
|
||||
$env:ZEN_RELEASE="true"
|
||||
$env:SURFER_SIGNING_MODE="true"
|
||||
Wait-Job -Name "SurferInit"
|
||||
Wait-Job -Name "DownloadGitl10n"
|
||||
|
||||
function SignAndPackage($name) {
|
||||
echo "Executing on $name"
|
||||
rmdir .\dist -Recurse -ErrorAction SilentlyContinue
|
||||
rmdir engine\obj-x86_64-pc-windows-msvc\ -Recurse -ErrorAction SilentlyContinue
|
||||
cp windsign-temp\windows-x64-obj-$name engine\obj-x86_64-pc-windows-msvc\ -Recurse
|
||||
echo "Signing $name"
|
||||
rmdir engine\obj-$name-pc-windows-msvc\ -Recurse -ErrorAction SilentlyContinue
|
||||
$objName=$name
|
||||
# instead of arm, use aarch64
|
||||
if ($name -eq "arm64") {
|
||||
$objName="aarch64"
|
||||
}
|
||||
|
||||
# Collect all .exe and .dll files into a list
|
||||
$files = Get-ChildItem engine\obj-x86_64-pc-windows-msvc\ -Recurse -Include *.exe
|
||||
$files += Get-ChildItem engine\obj-x86_64-pc-windows-msvc\ -Recurse -Include *.dll
|
||||
echo "Removing old obj dir"
|
||||
rmdir engine\obj-$objName-pc-windows-msvc\ -Recurse -ErrorAction SilentlyContinue
|
||||
|
||||
echo "Creating new obj dir"
|
||||
cp windsign-temp\windows-x64-obj-$name engine\obj-$objName-pc-windows-msvc\ -Recurse
|
||||
|
||||
signtool.exe sign /n "$SignIdentity" /t http://time.certum.pl/ /fd sha256 /v $files
|
||||
echo "Packaging $name"
|
||||
$env:SURFER_SIGNING_MODE="sign"
|
||||
$env:MAR="$PWD\\build\\winsign\\mar.exe"
|
||||
echo "Copying setup.exe into obj dir"
|
||||
$env:ZEN_SETUP_EXE_PATH="$PWD\windsign-temp\windows-x64-obj-$name\browser\installer\windows\instgen\setup.exe"
|
||||
|
||||
if ($name -eq "arm64") {
|
||||
$env:WIN32_REDIST_DIR="$PWD\win-cross\vs2022\VC\Redist\MSVC\14.38.33135\arm64\Microsoft.VC143.CRT"
|
||||
} else {
|
||||
$env:WIN32_REDIST_DIR="$PWD\win-cross\vs2022\VC\Redist\MSVC\14.38.33135\x64\Microsoft.VC143.CRT"
|
||||
}
|
||||
|
||||
$env:MAR="..\\build\\winsign\\mar.exe"
|
||||
if ($name -eq "arm64") {
|
||||
$env:SURFER_COMPAT="aarch64"
|
||||
} else {
|
||||
$env:SURFER_COMPAT="x86_64"
|
||||
}
|
||||
|
||||
echo "Compat Mode? $env:SURFER_COMPAT"
|
||||
|
||||
# Configure each time since we are cloning from a linux environment into
|
||||
# a windows environment, and the build system is not smart enough to detect that
|
||||
# we are on a different platform.
|
||||
cd .\engine
|
||||
echo "Configuring for $name"
|
||||
.\mach configure
|
||||
cd ..
|
||||
|
||||
echo "Packaging $name"
|
||||
npm run package -- --verbose
|
||||
|
||||
# In the release script, we do the following:
|
||||
@@ -62,7 +167,6 @@ function SignAndPackage($name) {
|
||||
# - update_manifest/*
|
||||
# - windows.mar
|
||||
# - zen.installer.exe
|
||||
# - zen.win-x86_64.zip
|
||||
echo "Creating tar for $name"
|
||||
rm .\windsign-temp\windows-x64-signed-$name -Recurse -ErrorAction SilentlyContinue
|
||||
mkdir windsign-temp\windows-x64-signed-$name
|
||||
@@ -83,30 +187,13 @@ function SignAndPackage($name) {
|
||||
mv .\dist\zen.installer.exe windsign-temp\windows-x64-signed-$name\zen.installer.exe
|
||||
}
|
||||
|
||||
# Move the zip
|
||||
echo "Moving zip for $name"
|
||||
if ($name -eq "arm64") {
|
||||
mv (Get-Item .\dist\*.en-US.win64-aarch64.zip) windsign-temp\windows-x64-signed-$name\zen.win-arm64.zip
|
||||
} else {
|
||||
mv (Get-Item .\dist\*.en-US.win64.zip) windsign-temp\windows-x64-signed-$name\zen.win-$name.zip
|
||||
}
|
||||
|
||||
# Extract the zip, sign everything inside, and repackage it
|
||||
Expand-Archive -Path windsign-temp\windows-x64-signed-$name\zen.win-$name.zip -DestinationPath windsign-temp\windows-x64-signed-$name\zen.win-$name
|
||||
rm windsign-temp\windows-x64-signed-$name\zen.win-$name.zip
|
||||
$files = Get-ChildItem windsign-temp\windows-x64-signed-$name\zen.win-$name -Recurse -Include *.exe
|
||||
$files += Get-ChildItem windsign-temp\windows-x64-signed-$name\zen.win-$name -Recurse -Include *.dll
|
||||
signtool.exe sign /n "$SignIdentity" /t http://time.certum.pl/ /fd sha256 /v $files
|
||||
Compress-Archive -Path windsign-temp\windows-x64-signed-$name\zen.win-$name -DestinationPath windsign-temp\windows-x64-signed-$name\zen.win-$name.zip
|
||||
rmdir windsign-temp\windows-x64-signed-$name\zen.win-$name -Recurse -ErrorAction SilentlyContinue
|
||||
|
||||
# Move the manifest
|
||||
mv .\dist\update\. windsign-temp\windows-x64-signed-$name\update_manifest
|
||||
|
||||
echo "Invoking tar for $name"
|
||||
# note: We need to sign it into a parent folder, called windows-x64-signed-$name
|
||||
rmdir .\windsign-temp\windows-binaries\windows-x64-signed-$name -Recurse -ErrorAction SilentlyContinue
|
||||
mv windsign-temp\windows-x64-signed-$name .\windsign-temp\windows-binaries -Force
|
||||
rmdir engine\obj-$objName-pc-windows-msvc\ -Recurse -ErrorAction SilentlyContinue
|
||||
|
||||
echo "Finished $name"
|
||||
}
|
||||
@@ -114,6 +201,9 @@ function SignAndPackage($name) {
|
||||
SignAndPackage arm64
|
||||
SignAndPackage x86_64
|
||||
|
||||
$files = Get-ChildItem .\windsign-temp\windows-binaries -Recurse -Include *.exe
|
||||
signtool.exe sign /n "$SignIdentity" /t http://time.certum.pl/ /fd sha256 /v $files
|
||||
|
||||
echo "All artifacts signed and packaged, ready for release!"
|
||||
echo "Commiting the changes to the repository"
|
||||
cd windsign-temp\windows-binaries
|
||||
|
@@ -17,7 +17,6 @@ if test "$ZEN_CROSS_COMPILING"; then
|
||||
else
|
||||
export WIN32_REDIST_DIR="$(echo ~)/win-cross/vs2022/VC/Redist/MSVC/14.38.33135/x64/Microsoft.VC143.CRT"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
#? https://bugzilla.mozilla.org/show_bug.cgi?id=1617793
|
||||
|
21
package-lock.json
generated
@@ -9,9 +9,10 @@
|
||||
"version": "1.0.0",
|
||||
"license": "MPL-2.0",
|
||||
"dependencies": {
|
||||
"@zen-browser/surfer": "^1.11.6"
|
||||
"@zen-browser/surfer": "^1.11.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"formal-git": "^1.1.5",
|
||||
"husky": "^9.1.7",
|
||||
"lint-staged": "^15.3.0",
|
||||
"prettier": "^3.4.2",
|
||||
@@ -288,9 +289,10 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@zen-browser/surfer": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@zen-browser/surfer/-/surfer-1.11.6.tgz",
|
||||
"integrity": "sha512-oKYjpNTPZV3vRxDf7r7pkvYlyNwL8cpsVbVzlb57xCwn7lamXsUioh1mLCSounJ+8cl8bWXhezrnXKXbVjyGww==",
|
||||
"version": "1.11.7",
|
||||
"resolved": "https://registry.npmjs.org/@zen-browser/surfer/-/surfer-1.11.7.tgz",
|
||||
"integrity": "sha512-ltIjDwPiSKmnKYjlTtD307t5h9+igi7YZu3pNlFl0SgvmTGRv9Ayit6CPllN5HGaMoI9jftOSeAaeFX2uRG4Yg==",
|
||||
"license": "MPL-2.0",
|
||||
"dependencies": {
|
||||
"@resvg/resvg-js": "^1.4.0",
|
||||
"async-icns": "^1.0.2",
|
||||
@@ -1027,6 +1029,17 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/formal-git": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/formal-git/-/formal-git-1.1.5.tgz",
|
||||
"integrity": "sha512-cSPoV0+/LFdUsE+fCGxCOK/eJNZeWj5c+6IxB3PP3QkeWIgdQFgw+RObnnpG/0KOsXy8mFrsD6tkEHbGjNGMpQ==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"fo": "lib/main.js",
|
||||
"formal-git": "lib/main.js"
|
||||
}
|
||||
},
|
||||
"node_modules/fs-constants": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||
|
@@ -40,9 +40,10 @@
|
||||
},
|
||||
"homepage": "https://github.com/zen-browser/desktop#readme",
|
||||
"dependencies": {
|
||||
"@zen-browser/surfer": "^1.11.6"
|
||||
"@zen-browser/surfer": "^1.11.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"formal-git": "^1.1.5",
|
||||
"husky": "^9.1.7",
|
||||
"lint-staged": "^15.3.0",
|
||||
"prettier": "^3.4.2",
|
||||
|
@@ -1,4 +1,12 @@
|
||||
set -ex
|
||||
set -x
|
||||
|
||||
if ! [ -z "$ZEN_L10N_CURR_DIR" ]; then
|
||||
cd $ZEN_L10N_CURR_DIR
|
||||
fi
|
||||
|
||||
# remove "\r" from ./l10n/supported-languages
|
||||
# note: it's fine if it fails
|
||||
sed -i 's/\r$//' ./l10n/supported-languages
|
||||
|
||||
CURRENT_DIR=$(pwd)
|
||||
|
||||
@@ -17,6 +25,16 @@ cd firefox-l10n
|
||||
git checkout $LAST_FIREFOX_L10N_COMMIT
|
||||
cd $CURRENT_DIR
|
||||
|
||||
rsyncExists=$(command -v rsync)
|
||||
|
||||
if [ -z "$rsyncExists" ]; then
|
||||
echo "rsync not found, using cp instead"
|
||||
else
|
||||
echo "rsync found!"
|
||||
fi
|
||||
|
||||
set -e
|
||||
|
||||
update_language() {
|
||||
langId=$1
|
||||
cd ./l10n
|
||||
@@ -24,7 +42,13 @@ update_language() {
|
||||
|
||||
echo "Updating $langId"
|
||||
# move the contents from ../firefox-l10n/$langId to ./l10n/$langId
|
||||
rsync -av --progress ../firefox-l10n/$langId/ . --exclude .git
|
||||
# if rsync exists, use it
|
||||
# if not, use cp
|
||||
if [ -z "$rsyncExists" ]; then
|
||||
cp -r $CURRENT_DIR/l10n/firefox-l10n/$langId/* .
|
||||
else
|
||||
rsync -av --progress ../firefox-l10n/$langId/ . --exclude .git
|
||||
fi
|
||||
|
||||
cd $CURRENT_DIR
|
||||
}
|
||||
|
30
scripts/fetch-formal-git-components.sh
Normal file
@@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
COMPONENT_ROOT=$(pwd)/src/zen
|
||||
|
||||
EXTRA_COMPONENTS=(
|
||||
"scripts"
|
||||
"workflows"
|
||||
"winsign"
|
||||
"flatpak"
|
||||
"configs"
|
||||
)
|
||||
|
||||
echo "" > .formal-git/components
|
||||
|
||||
# iterate top directories and adding the base name to .formal-git/components
|
||||
for dir in $(find $COMPONENT_ROOT -maxdepth 1 -type d | grep -v '\.git' | grep -v 'node_modules' | grep -v 'engine'); do
|
||||
if [ "$dir" != "$COMPONENT_ROOT" ]; then
|
||||
echo "$(basename $dir)" >> .formal-git/components
|
||||
fi
|
||||
done
|
||||
|
||||
# iterate over the extra components and adding them to .formal-git/components
|
||||
for extra in "${EXTRA_COMPONENTS[@]}"; do
|
||||
echo "$extra" >> .formal-git/components
|
||||
done
|
||||
|
||||
# remove all empty lines
|
||||
sed -i '/^$/d' .formal-git/components
|
12
src/browser/actors/WebRTCParent-sys-mjs.patch
Normal file
@@ -0,0 +1,12 @@
|
||||
diff --git a/browser/actors/WebRTCParent.sys.mjs b/browser/actors/WebRTCParent.sys.mjs
|
||||
index be66de4a1ef044341c2e1d6953806550897df45a..ff6ef3511076b25e00ca4d0189f666ec7aa94fe8 100644
|
||||
--- a/browser/actors/WebRTCParent.sys.mjs
|
||||
+++ b/browser/actors/WebRTCParent.sys.mjs
|
||||
@@ -152,6 +152,7 @@ export class WebRTCParent extends JSWindowActorParent {
|
||||
|
||||
let tabbrowser = browser.ownerGlobal.gBrowser;
|
||||
if (tabbrowser) {
|
||||
+ browser.ownerGlobal.gZenMediaController.updateMediaSharing(state);
|
||||
tabbrowser.updateBrowserSharing(browser, {
|
||||
webRTC: state,
|
||||
});
|
@@ -1,8 +1,8 @@
|
||||
diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js
|
||||
index 97acbf826f9427b06e0a54679b30269ce7b695f5..aeadcd0c72816612cd5c1ca1199fe2a363c637f4 100644
|
||||
index 78572e5480a6137c5b7de89c489956f5d68ef698..1c72fe9a5419e211dea25271113981aeda46ec66 100644
|
||||
--- a/browser/app/profile/firefox.js
|
||||
+++ b/browser/app/profile/firefox.js
|
||||
@@ -3362,3 +3362,5 @@ pref("toolkit.contentRelevancy.enabled", false);
|
||||
@@ -3363,3 +3363,5 @@ pref("toolkit.contentRelevancy.enabled", false);
|
||||
pref("toolkit.contentRelevancy.ingestEnabled", false);
|
||||
// Pref to enable extra logging for the content relevancy feature
|
||||
pref("toolkit.contentRelevancy.log", false);
|
||||
|
@@ -19,6 +19,7 @@ pref("intl.multilingual.downloadEnabled", false);
|
||||
|
||||
// Restore session on startup
|
||||
pref("browser.startup.page", 3);
|
||||
pref("browser.sessionstore.restore_pinned_tabs_on_demand", true);
|
||||
|
||||
// Theme
|
||||
pref('toolkit.legacyUserProfileCustomizations.stylesheets', true);
|
||||
@@ -26,6 +27,10 @@ pref('browser.compactmode.show', true);
|
||||
|
||||
#ifdef XP_WIN
|
||||
pref("browser.privateWindowSeparation.enabled", false);
|
||||
|
||||
// Mica
|
||||
pref("widget.windows.mica", true);
|
||||
pref("widget.windows.mica.popups", true);
|
||||
#endif
|
||||
|
||||
pref('browser.newtabpage.activity-stream.newtabWallpapers.enabled', true);
|
||||
@@ -312,10 +317,13 @@ pref("mousewheel.default.delta_multiplier_y", 200);
|
||||
#endif
|
||||
|
||||
#if defined(XP_WIN)
|
||||
pref("dom.ipc.processPriorityManager.backgroundUsesEcoQoS", false);
|
||||
pref("dom.ipc.processPriorityManager.backgroundUsesEcoQoS", false);
|
||||
#endif
|
||||
|
||||
#ifdef UNIX_BUT_NOT_MAC
|
||||
pref("widget.gtk.rounded-bottom-corners.enabled", true);
|
||||
#endif
|
||||
|
||||
pref('browser.sessionstore.restore_pinned_tabs_on_demand', true);
|
||||
pref('browser.newtabpage.activity-stream.system.showWeather', true);
|
||||
|
||||
// Enable experimental settings page (Used for Zen Labs)
|
||||
@@ -380,6 +388,11 @@ pref('widget.macos.titlebar-blend-mode.behind-window', true);
|
||||
pref('zen.widget.macos.window-material', 3);
|
||||
#endif
|
||||
|
||||
// Enable transparent background for linux
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
pref('zen.widget.linux.transparency', false);
|
||||
#endif
|
||||
|
||||
// Urlbar and autocomplete
|
||||
pref("browser.urlbar.maxRichResults", 6);
|
||||
pref("browser.urlbar.trimHttps", true);
|
||||
@@ -459,3 +472,8 @@ pref("image.mem.decode_bytes_at_a_time", 32768);
|
||||
pref("gfx.canvas.accelerated", true);
|
||||
pref("media.hardware-video-decoding.enabled", true);
|
||||
pref("layers.gpu-process.enabled", true);
|
||||
|
||||
// Picture-in-picture
|
||||
pref("media.videocontrols.picture-in-picture.video-toggle.enabled", true);
|
||||
// TODO: Enable once we have a proper settings page
|
||||
pref("media.videocontrols.picture-in-picture.enable-when-switching-tabs.enabled", false);
|
||||
|
@@ -10,7 +10,6 @@
|
||||
<link rel="stylesheet" type="text/css" href="chrome://browser/content/zen-styles/zen-tabs.css" />
|
||||
<link rel="stylesheet" type="text/css" href="chrome://browser/content/zen-styles/zen-browser-ui.css" />
|
||||
<link rel="stylesheet" type="text/css" href="chrome://browser/content/zen-styles/zen-gradient-generator.css" />
|
||||
<link rel="stylesheet" type="text/css" href="chrome://browser/content/zen-styles/zen-rices.css" />
|
||||
<link rel="stylesheet" type="text/css" href="chrome://browser/content/zen-styles/zen-panel-ui.css" />
|
||||
<link rel="stylesheet" type="text/css" href="chrome://browser/content/zen-styles/zen-single-components.css" />
|
||||
<link rel="stylesheet" type="text/css" href="chrome://browser/content/zen-styles/zen-browser-container.css" />
|
||||
@@ -43,7 +42,4 @@ Services.scriptloader.loadSubScript("chrome://browser/content/zen-components/Zen
|
||||
Services.scriptloader.loadSubScript("chrome://browser/content/zen-components/ZenViewSplitter.mjs", this);
|
||||
Services.scriptloader.loadSubScript("chrome://browser/content/zen-components/ZenGlanceManager.mjs", this);
|
||||
Services.scriptloader.loadSubScript("chrome://browser/content/zen-components/ZenMediaController.mjs", this);
|
||||
|
||||
// Unimportant scripts
|
||||
Services.scriptloader.loadSubScript("chrome://browser/content/zen-components/ZenRices.mjs", this);
|
||||
</script>
|
||||
|
@@ -1,82 +1,87 @@
|
||||
|
||||
|
||||
content/browser/zenThemeModifier.js (content/zenThemeModifier.js)
|
||||
content/browser/ZenStartup.mjs (content/ZenStartup.mjs)
|
||||
content/browser/zen-sets.js (content/zen-sets.js)
|
||||
content/browser/ZenUIManager.mjs (content/ZenUIManager.mjs)
|
||||
content/browser/ZenCustomizableUI.sys.mjs (content/ZenCustomizableUI.sys.mjs)
|
||||
content/browser/zen-components/ZenUIMigration.mjs (zen-components/ZenUIMigration.mjs)
|
||||
content/browser/zen-components/ZenCompactMode.mjs (zen-components/ZenCompactMode.mjs)
|
||||
content/browser/zen-components/ZenViewSplitter.mjs (zen-components/ZenViewSplitter.mjs)
|
||||
content/browser/zen-components/ZenThemesCommon.mjs (zen-components/ZenThemesCommon.mjs)
|
||||
content/browser/zen-components/ZenWorkspaces.mjs (zen-components/ZenWorkspaces.mjs)
|
||||
content/browser/zen-components/ZenWorkspacesStorage.mjs (zen-components/ZenWorkspacesStorage.mjs)
|
||||
content/browser/zen-components/ZenWorkspacesSync.mjs (zen-components/ZenWorkspacesSync.mjs)
|
||||
content/browser/zen-components/ZenKeyboardShortcuts.mjs (zen-components/ZenKeyboardShortcuts.mjs)
|
||||
content/browser/zen-components/ZenThemesImporter.mjs (zen-components/ZenThemesImporter.mjs)
|
||||
content/browser/zen-components/ZenTabUnloader.mjs (zen-components/ZenTabUnloader.mjs)
|
||||
content/browser/zen-components/ZenPinnedTabsStorage.mjs (zen-components/ZenPinnedTabsStorage.mjs)
|
||||
content/browser/zen-components/ZenPinnedTabManager.mjs (zen-components/ZenPinnedTabManager.mjs)
|
||||
content/browser/zen-components/ZenCommonUtils.mjs (zen-components/ZenCommonUtils.mjs)
|
||||
content/browser/zen-components/ZenGradientGenerator.mjs (zen-components/ZenGradientGenerator.mjs)
|
||||
content/browser/zen-components/ZenGlanceManager.mjs (zen-components/ZenGlanceManager.mjs)
|
||||
content/browser/zen-components/ZenFolders.mjs (zen-components/ZenFolders.mjs)
|
||||
content/browser/zen-components/ZenActorsManager.mjs (zen-components/ZenActorsManager.mjs)
|
||||
content/browser/zen-components/ZenRices.mjs (zen-components/ZenRices.mjs)
|
||||
content/browser/zen-components/ZenEmojies.mjs (zen-components/ZenEmojies.mjs)
|
||||
content/browser/zen-components/ZenWelcome.mjs (zen-components/ZenWelcome.mjs)
|
||||
content/browser/zen-components/ZenMediaController.mjs (zen-components/ZenMediaController.mjs)
|
||||
content/browser/zenThemeModifier.js (../../zen/common/zenThemeModifier.js)
|
||||
content/browser/ZenStartup.mjs (../../zen/common/ZenStartup.mjs)
|
||||
content/browser/zen-sets.js (../../zen/common/zen-sets.js)
|
||||
content/browser/ZenUIManager.mjs (../../zen/common/ZenUIManager.mjs)
|
||||
content/browser/zen-components/ZenActorsManager.mjs (../../zen/common/ZenActorsManager.mjs)
|
||||
content/browser/zen-components/ZenEmojies.mjs (../../zen/common/ZenEmojies.mjs)
|
||||
content/browser/ZenCustomizableUI.sys.mjs (../../zen/common/ZenCustomizableUI.sys.mjs)
|
||||
content/browser/zen-components/ZenUIMigration.mjs (../../zen/common/ZenUIMigration.mjs)
|
||||
content/browser/zen-components/ZenCommonUtils.mjs (../../zen/common/ZenCommonUtils.mjs)
|
||||
|
||||
content/browser/zen-styles/zen-theme.css (content/zen-styles/zen-theme.css)
|
||||
content/browser/zen-styles/zen-buttons.css (content/zen-styles/zen-buttons.css)
|
||||
content/browser/zen-styles/zen-tabs.css (content/zen-styles/zen-tabs.css)
|
||||
* content/browser/zen-styles/zen-tabs/vertical-tabs.css (content/zen-styles/zen-tabs/vertical-tabs.css)
|
||||
content/browser/zen-styles/zen-tabs/horizontal-tabs.css (content/zen-styles/zen-tabs/horizontal-tabs.css)
|
||||
content/browser/zen-styles/zen-browser-ui.css (content/zen-styles/zen-browser-ui.css)
|
||||
content/browser/zen-styles/zen-animations.css (content/zen-styles/zen-animations.css)
|
||||
content/browser/zen-styles/zen-panel-ui.css (content/zen-styles/zen-panel-ui.css)
|
||||
content/browser/zen-styles/zen-single-components.css (content/zen-styles/zen-single-components.css)
|
||||
content/browser/zen-styles/zen-sidebar.css (content/zen-styles/zen-sidebar.css)
|
||||
content/browser/zen-styles/zen-toolbar.css (content/zen-styles/zen-toolbar.css)
|
||||
content/browser/zen-styles/zen-decks.css (content/zen-styles/zen-decks.css)
|
||||
content/browser/zen-styles/zen-folders.css (content/zen-styles/zen-folders.css)
|
||||
content/browser/zen-styles/zen-glance.css (content/zen-styles/zen-glance.css)
|
||||
content/browser/zen-styles/zen-browser-container.css (content/zen-styles/zen-browser-container.css)
|
||||
content/browser/zen-styles/zen-workspaces.css (content/zen-styles/zen-workspaces.css)
|
||||
content/browser/zen-styles/zen-urlbar.css (content/zen-styles/zen-urlbar.css)
|
||||
content/browser/zen-styles/zen-popup.css (content/zen-styles/zen-popup.css)
|
||||
content/browser/zen-styles/zen-gradient-generator.css (content/zen-styles/zen-gradient-generator.css)
|
||||
content/browser/zen-styles/zen-rices.css (content/zen-styles/zen-rices.css)
|
||||
content/browser/zen-styles/zen-branding.css (content/zen-styles/zen-branding.css)
|
||||
content/browser/zen-styles/zen-welcome.css (content/zen-styles/zen-welcome.css)
|
||||
content/browser/zen-styles/zen-media-controls.css (content/zen-styles/zen-media-controls.css)
|
||||
content/browser/zen-styles/zen-theme.css (../../zen/common/styles/zen-theme.css)
|
||||
content/browser/zen-styles/zen-buttons.css (../../zen/common/styles/zen-buttons.css)
|
||||
content/browser/zen-styles/zen-browser-ui.css (../../zen/common/styles/zen-browser-ui.css)
|
||||
content/browser/zen-styles/zen-animations.css (../../zen/common/styles/zen-animations.css)
|
||||
content/browser/zen-styles/zen-panel-ui.css (../../zen/common/styles/zen-panel-ui.css)
|
||||
content/browser/zen-styles/zen-single-components.css (../../zen/common/styles/zen-single-components.css)
|
||||
content/browser/zen-styles/zen-sidebar.css (../../zen/common/styles/zen-sidebar.css)
|
||||
content/browser/zen-styles/zen-toolbar.css (../../zen/common/styles/zen-toolbar.css)
|
||||
content/browser/zen-styles/zen-browser-container.css (../../zen/common/styles/zen-browser-container.css)
|
||||
content/browser/zen-styles/zen-urlbar.css (../../zen/common/styles/zen-urlbar.css)
|
||||
content/browser/zen-styles/zen-popup.css (../../zen/common/styles/zen-popup.css)
|
||||
content/browser/zen-styles/zen-branding.css (../../zen/common/styles/zen-branding.css)
|
||||
|
||||
content/browser/zen-styles/zen-panels/bookmarks.css (content/zen-styles/zen-panels/bookmarks.css)
|
||||
content/browser/zen-styles/zen-panels/extensions.css (content/zen-styles/zen-panels/extensions.css)
|
||||
content/browser/zen-styles/zen-panels/print.css (content/zen-styles/zen-panels/print.css)
|
||||
content/browser/zen-styles/zen-panels/dialog.css (content/zen-styles/zen-panels/dialog.css)
|
||||
content/browser/zen-styles/zen-panels/bookmarks.css (../../zen/common/styles/zen-panels/bookmarks.css)
|
||||
content/browser/zen-styles/zen-panels/extensions.css (../../zen/common/styles/zen-panels/extensions.css)
|
||||
content/browser/zen-styles/zen-panels/print.css (../../zen/common/styles/zen-panels/print.css)
|
||||
content/browser/zen-styles/zen-panels/dialog.css (../../zen/common/styles/zen-panels/dialog.css)
|
||||
|
||||
* content/browser/zen-styles/zen-compact-mode.css (content/zen-styles/zen-compact-mode.css)
|
||||
content/browser/zen-components/ZenCompactMode.mjs (../../zen/compact-mode/ZenCompactMode.mjs)
|
||||
* content/browser/zen-styles/zen-compact-mode.css (../../zen/compact-mode/zen-compact-mode.css)
|
||||
|
||||
# Images
|
||||
content/browser/zen-images/gradient.png (content/zen-images/gradient.png)
|
||||
content/browser/zen-images/brand-header.svg (content/zen-images/brand-header.svg)
|
||||
content/browser/zen-images/layouts/collapsed.png (content/zen-images/layouts/collapsed.png)
|
||||
content/browser/zen-images/layouts/multiple-toolbar.png (content/zen-images/layouts/multiple-toolbar.png)
|
||||
content/browser/zen-images/layouts/single-toolbar.png (content/zen-images/layouts/single-toolbar.png)
|
||||
content/browser/zen-images/grain-bg.png (content/zen-images/grain-bg.png)
|
||||
content/browser/zen-images/note-indicator.svg (content/zen-images/note-indicator.svg)
|
||||
content/browser/zen-components/ZenViewSplitter.mjs (../../zen/split-view/ZenViewSplitter.mjs)
|
||||
content/browser/zen-styles/zen-decks.css (../../zen/split-view/zen-decks.css)
|
||||
|
||||
# Actors
|
||||
content/browser/zen-components/actors/ZenThemeMarketplaceParent.sys.mjs (zen-components/actors/ZenThemeMarketplaceParent.sys.mjs)
|
||||
content/browser/zen-components/actors/ZenThemeMarketplaceChild.sys.mjs (zen-components/actors/ZenThemeMarketplaceChild.sys.mjs)
|
||||
content/browser/zen-components/actors/ZenGlanceChild.sys.mjs (zen-components/actors/ZenGlanceChild.sys.mjs)
|
||||
content/browser/zen-components/actors/ZenGlanceParent.sys.mjs (zen-components/actors/ZenGlanceParent.sys.mjs)
|
||||
content/browser/zen-components/ZenThemesCommon.mjs (../../zen/mods/ZenThemesCommon.mjs)
|
||||
content/browser/zen-components/ZenThemesImporter.mjs (../../zen/mods/ZenThemesImporter.mjs)
|
||||
content/browser/zen-components/actors/ZenThemeMarketplaceParent.sys.mjs (../../zen/mods/actors/ZenThemeMarketplaceParent.sys.mjs)
|
||||
content/browser/zen-components/actors/ZenThemeMarketplaceChild.sys.mjs (../../zen/mods/actors/ZenThemeMarketplaceChild.sys.mjs)
|
||||
|
||||
# Fonts
|
||||
content/browser/zen-fonts/JunicodeVF-Italic.woff2 (content/zen-fonts/JunicodeVF-Italic.woff2)
|
||||
content/browser/zen-fonts/JunicodeVF-Roman.woff2 (content/zen-fonts/JunicodeVF-Roman.woff2)
|
||||
content/browser/zen-components/ZenWorkspaces.mjs (../../zen/workspaces/ZenWorkspaces.mjs)
|
||||
content/browser/zen-components/ZenWorkspacesStorage.mjs (../../zen/workspaces/ZenWorkspacesStorage.mjs)
|
||||
content/browser/zen-components/ZenWorkspacesSync.mjs (../../zen/workspaces/ZenWorkspacesSync.mjs)
|
||||
content/browser/zen-components/ZenGradientGenerator.mjs (../../zen/workspaces/ZenGradientGenerator.mjs)
|
||||
content/browser/zen-styles/zen-workspaces.css (../../zen/workspaces/zen-workspaces.css)
|
||||
content/browser/zen-styles/zen-gradient-generator.css (../../zen/workspaces/zen-gradient-generator.css)
|
||||
|
||||
content/browser/zen-components/ZenKeyboardShortcuts.mjs (../../zen/kbs/ZenKeyboardShortcuts.mjs)
|
||||
|
||||
content/browser/zen-components/ZenTabUnloader.mjs (../../zen/tabs/ZenTabUnloader.mjs)
|
||||
content/browser/zen-components/ZenPinnedTabsStorage.mjs (../../zen/tabs/ZenPinnedTabsStorage.mjs)
|
||||
content/browser/zen-components/ZenPinnedTabManager.mjs (../../zen/tabs/ZenPinnedTabManager.mjs)
|
||||
content/browser/zen-styles/zen-tabs.css (../../zen/tabs/zen-tabs.css)
|
||||
* content/browser/zen-styles/zen-tabs/vertical-tabs.css (../../zen/tabs/zen-tabs/vertical-tabs.css)
|
||||
content/browser/zen-styles/zen-tabs/horizontal-tabs.css (../../zen/tabs/zen-tabs/horizontal-tabs.css)
|
||||
|
||||
content/browser/zen-components/ZenGlanceManager.mjs (../../zen/glance/ZenGlanceManager.mjs)
|
||||
content/browser/zen-styles/zen-glance.css (../../zen/glance/zen-glance.css)
|
||||
content/browser/zen-components/actors/ZenGlanceChild.sys.mjs (../../zen/glance/actors/ZenGlanceChild.sys.mjs)
|
||||
content/browser/zen-components/actors/ZenGlanceParent.sys.mjs (../../zen/glance/actors/ZenGlanceParent.sys.mjs)
|
||||
|
||||
content/browser/zen-components/ZenFolders.mjs (../../zen/folders/ZenFolders.mjs)
|
||||
content/browser/zen-styles/zen-folders.css (../../zen/folders/zen-folders.css)
|
||||
|
||||
content/browser/zen-components/ZenWelcome.mjs (../../zen/welcome/ZenWelcome.mjs)
|
||||
content/browser/zen-styles/zen-welcome.css (../../zen/welcome/zen-welcome.css)
|
||||
|
||||
content/browser/zen-components/ZenMediaController.mjs (../../zen/media/ZenMediaController.mjs)
|
||||
content/browser/zen-styles/zen-media-controls.css (../../zen/media/zen-media-controls.css)
|
||||
|
||||
# Images
|
||||
content/browser/zen-images/gradient.png (../../zen/images/gradient.png)
|
||||
content/browser/zen-images/brand-header.svg (../../zen/images/brand-header.svg)
|
||||
content/browser/zen-images/layouts/collapsed.png (../../zen/images/layouts/collapsed.png)
|
||||
content/browser/zen-images/layouts/multiple-toolbar.png (../../zen/images/layouts/multiple-toolbar.png)
|
||||
content/browser/zen-images/layouts/single-toolbar.png (../../zen/images/layouts/single-toolbar.png)
|
||||
content/browser/zen-images/grain-bg.png (../../zen/images/grain-bg.png)
|
||||
content/browser/zen-images/note-indicator.svg (../../zen/images/note-indicator.svg)
|
||||
|
||||
# Fonts
|
||||
content/browser/zen-fonts/JunicodeVF-Italic.woff2 (../../zen/fonts/JunicodeVF-Italic.woff2)
|
||||
content/browser/zen-fonts/JunicodeVF-Roman.woff2 (../../zen/fonts/JunicodeVF-Roman.woff2)
|
||||
|
||||
# JS Vendor
|
||||
content/browser/zen-vendor/tsparticles.confetti.bundle.min.js (content/zen-vendor/tsparticles.confetti.bundle.min.js)
|
||||
content/browser/zen-vendor/motion.min.mjs (content/zen-vendor/motion.min.mjs)
|
||||
content/browser/zen-vendor/tsparticles.confetti.bundle.min.js (../../zen/vendor/tsparticles.confetti.bundle.min.js)
|
||||
content/browser/zen-vendor/motion.min.mjs (../../zen/vendor/motion.min.mjs)
|
||||
|
@@ -1,4 +1,4 @@
|
||||
#include zen-media-player.inc.xhtml
|
||||
#include ../../../zen/media/zen-media-controls.inc.xhtml
|
||||
<toolbar brighttext="true"
|
||||
id="zen-sidebar-bottom-buttons"
|
||||
fullscreentoolbar="true"
|
||||
|
@@ -1,226 +0,0 @@
|
||||
#zen-rice-share-dialog-overlay:not([hidden]) {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
z-index: 3;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#zen-rice-share-dialog,
|
||||
#zen-rice-share-dialog-notice {
|
||||
color: var(--panel-color);
|
||||
background: var(--arrowpanel-background);
|
||||
border-radius: var(--zen-native-inner-radius);
|
||||
box-shadow: 0 0 1px 1px hsla(0, 0%, 0%, 0.2);
|
||||
border: var(--zen-appcontent-border);
|
||||
overflow: hidden;
|
||||
|
||||
animation: zen-jello-animation-large 0.4s ease;
|
||||
max-width: 400px;
|
||||
|
||||
&[animate='true'] {
|
||||
animation: zen-rice-submit-animation 1s cubic-bezier(0.77, 0, 0.18, 1);
|
||||
}
|
||||
|
||||
& .zen-rice-share-content {
|
||||
padding: 10px 0;
|
||||
border-top: var(--zen-appcontent-border);
|
||||
background: var(--arrowpanel-background);
|
||||
position: relative;
|
||||
align-items: center;
|
||||
|
||||
min-height: 50px;
|
||||
|
||||
&:has(#zen-rice-share-first-form:not([fade-out])),
|
||||
&:has(#zen-rice-share-success) {
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
& > vbox {
|
||||
width: 100%;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
& #zen-rice-share-first-form input[type='text'] {
|
||||
width: 100%;
|
||||
padding: 1px 2px;
|
||||
border: 0;
|
||||
border-bottom: 1px solid var(--zen-appcontent-border);
|
||||
background: transparent;
|
||||
font-style: italic;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
& #zen-rice-share-name {
|
||||
font-style: normal !important;
|
||||
font-size: 24px;
|
||||
margin-left: 1px;
|
||||
}
|
||||
|
||||
& .indent {
|
||||
margin-left: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
& .zen-rice-share-header {
|
||||
height: 200px;
|
||||
margin-bottom: -20px;
|
||||
}
|
||||
|
||||
& #zen-rice-share-options {
|
||||
padding: 10px 0;
|
||||
|
||||
max-height: 30px;
|
||||
overflow: hidden;
|
||||
transition:
|
||||
max-height 0.3s ease,
|
||||
height 0.3s ease;
|
||||
&[zen-collapsed='false'] {
|
||||
max-height: 350px;
|
||||
}
|
||||
|
||||
& > .options-header {
|
||||
font-weight: 600;
|
||||
margin-bottom: 5px;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
align-items: center;
|
||||
|
||||
color: inherit;
|
||||
-moz-context-properties: fill, fill-opacity;
|
||||
fill: var(--toolbarbutton-icon-fill);
|
||||
|
||||
& label {
|
||||
width: fit-content;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
& > .options-header image {
|
||||
transition: transform 0.3s ease;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
&[zen-collapsed='false'] > .options-header image {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
& > checkbox {
|
||||
margin-left: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
& .panel-footer {
|
||||
margin: 0;
|
||||
margin-top: 10px;
|
||||
|
||||
& button {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
#zen-rice-share-error {
|
||||
border: 1px solid rgba(255, 0, 0, 0.5);
|
||||
background: rgba(255, 0, 0, 0.1);
|
||||
padding: 5px;
|
||||
transition: opacity 0.3s ease;
|
||||
border-radius: var(--zen-native-inner-radius);
|
||||
|
||||
@starting-style {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
& button {
|
||||
margin-left: auto;
|
||||
margin-top: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Animations */
|
||||
#zen-rice-share-first-form[fade-out] {
|
||||
position: absolute;
|
||||
transform: translateX(-100%);
|
||||
pointer-events: none;
|
||||
animation: zen-rice-form-out 0.5s ease;
|
||||
}
|
||||
|
||||
#zen-rice-share-second-form {
|
||||
animation: zen-rice-form-in 0.5s ease forwards;
|
||||
justify-content: center;
|
||||
|
||||
& > hbox {
|
||||
width: 100%;
|
||||
height: 5px;
|
||||
border-radius: 100px;
|
||||
border: 1px solid var(--zen-colors-border);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: var(--zen-primary-color);
|
||||
transition: width 4s cubic-bezier(1, 0, 0, 1);
|
||||
|
||||
@starting-style {
|
||||
width: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&[fade-out] {
|
||||
position: absolute !important;
|
||||
animation: zen-rice-form-out 0.5s ease forwards;
|
||||
}
|
||||
}
|
||||
|
||||
#zen-rice-share-success {
|
||||
overflow-y: hidden;
|
||||
max-height: 0px;
|
||||
animation: zen-rice-form-in-2 0.5s ease forwards;
|
||||
|
||||
& > h1 {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
& > p {
|
||||
color: var(--text-color-deemphasized);
|
||||
}
|
||||
|
||||
& label {
|
||||
margin: 0;
|
||||
margin-top: 15px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#zen-rice-share-dialog-notice {
|
||||
padding: 15px;
|
||||
|
||||
& br {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
& > p {
|
||||
color: var(--text-color-deemphasized);
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.panel-footer {
|
||||
margin-top: 10px;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
@@ -1,2 +1,2 @@
|
||||
#include zen-splitview-overlay.inc.xhtml
|
||||
#include zen-glance.inc.xhtml
|
||||
#include ../../../zen/split-view/zen-splitview-overlay.inc.xhtml
|
||||
#include ../../../zen/glance/zen-glance.inc.xhtml
|
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/base/moz.build b/browser/base/moz.build
|
||||
index 636e0841786735a63ddea00e819c0b6f0b8a5d4d..6685d857180944d68bf4f049919f81361084c481 100644
|
||||
index 636e0841786735a63ddea00e819c0b6f0b8a5d4d..62e4531bd19caf098fd76c69b213fa32d62546a6 100644
|
||||
--- a/browser/base/moz.build
|
||||
+++ b/browser/base/moz.build
|
||||
@@ -87,3 +87,5 @@ if CONFIG["MOZ_WIDGET_TOOLKIT"] in ("windows", "gtk"):
|
||||
@@ -7,4 +7,4 @@ index 636e0841786735a63ddea00e819c0b6f0b8a5d4d..6685d857180944d68bf4f049919f8136
|
||||
|
||||
JAR_MANIFESTS += ["jar.mn"]
|
||||
+
|
||||
+DIRS += ["zen-components"]
|
||||
+DIRS += ["../../zen"]
|
||||
|
@@ -1,533 +0,0 @@
|
||||
class ZenMediaController {
|
||||
_currentMediaController = null;
|
||||
_currentBrowser = null;
|
||||
_mediaUpdateInterval = null;
|
||||
|
||||
mediaTitle = null;
|
||||
mediaArtist = null;
|
||||
mediaControlBar = null;
|
||||
mediaProgressBar = null;
|
||||
mediaCurrentTime = null;
|
||||
mediaDuration = null;
|
||||
mediaFocusButton = null;
|
||||
mediaProgressBarContainer = null;
|
||||
|
||||
supportedKeys = ['playpause', 'previoustrack', 'nexttrack'];
|
||||
|
||||
pipEligibilityMap = new Map();
|
||||
mediaControllersMap = new Map();
|
||||
|
||||
_tabTimeout = null;
|
||||
_controllerSwitchTimeout = null;
|
||||
|
||||
init() {
|
||||
if (!Services.prefs.getBoolPref('zen.mediacontrols.enabled', true)) return;
|
||||
|
||||
this.mediaTitle = document.querySelector('#zen-media-title');
|
||||
this.mediaArtist = document.querySelector('#zen-media-artist');
|
||||
this.mediaControlBar = document.querySelector('#zen-media-controls-toolbar');
|
||||
this.mediaProgressBar = document.querySelector('#zen-media-progress-bar');
|
||||
this.mediaCurrentTime = document.querySelector('#zen-media-current-time');
|
||||
this.mediaDuration = document.querySelector('#zen-media-duration');
|
||||
this.mediaFocusButton = document.querySelector('#zen-media-focus-button');
|
||||
this.mediaProgressBarContainer = document.querySelector('#zen-media-progress-hbox');
|
||||
|
||||
this.onPositionstateChange = this._onPositionstateChange.bind(this);
|
||||
this.onPlaybackstateChange = this._onPlaybackstateChange.bind(this);
|
||||
this.onSupportedKeysChange = this._onSupportedKeysChange.bind(this);
|
||||
this.onMetadataChange = this._onMetadataChange.bind(this);
|
||||
this.onDeactivated = this._onDeactivated.bind(this);
|
||||
this.onPipModeChange = this._onPictureInPictureModeChange.bind(this);
|
||||
|
||||
this.#initEventListeners();
|
||||
}
|
||||
|
||||
#initEventListeners() {
|
||||
this.mediaControlBar.addEventListener('command', (event) => {
|
||||
const button = event.target.closest('toolbarbutton');
|
||||
if (!button) return;
|
||||
switch (button.id) {
|
||||
case 'zen-media-pip-button':
|
||||
this.onMediaPip();
|
||||
break;
|
||||
case 'zen-media-close-button':
|
||||
this.onControllerClose();
|
||||
break;
|
||||
case 'zen-media-focus-button':
|
||||
this.onMediaFocus();
|
||||
break;
|
||||
case 'zen-media-mute-button':
|
||||
this.onMediaMute();
|
||||
break;
|
||||
case 'zen-media-previoustrack-button':
|
||||
this.onMediaPlayPrev();
|
||||
break;
|
||||
case 'zen-media-nexttrack-button':
|
||||
this.onMediaPlayNext();
|
||||
break;
|
||||
case 'zen-media-playpause-button':
|
||||
this.onMediaToggle();
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
this.mediaProgressBar.addEventListener('input', this.onMediaSeekDrag.bind(this));
|
||||
this.mediaProgressBar.addEventListener('change', this.onMediaSeekComplete.bind(this));
|
||||
|
||||
window.addEventListener('TabSelect', (event) => {
|
||||
const linkedBrowser = event.target.linkedBrowser;
|
||||
this.switchController();
|
||||
|
||||
if (this._currentBrowser) {
|
||||
if (linkedBrowser.browserId === this._currentBrowser.browserId) {
|
||||
if (this._tabTimeout) {
|
||||
clearTimeout(this._tabTimeout);
|
||||
this._tabTimeout = null;
|
||||
}
|
||||
|
||||
this.hideMediaControls();
|
||||
} else {
|
||||
this._tabTimeout = setTimeout(() => {
|
||||
if (!this.mediaControlBar.hasAttribute('pip')) this.showMediaControls();
|
||||
else this._tabTimeout = null;
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const onTabDiscardedOrClosed = this.onTabDiscardedOrClosed.bind(this);
|
||||
window.addEventListener('TabClose', onTabDiscardedOrClosed);
|
||||
|
||||
window.addEventListener('DOMAudioPlaybackStarted', (event) => {
|
||||
setTimeout(() => {
|
||||
if (
|
||||
this._currentMediaController?.isPlaying &&
|
||||
this.mediaControlBar.hasAttribute('hidden') &&
|
||||
!this.mediaControlBar.hasAttribute('pip')
|
||||
) {
|
||||
const { selectedBrowser } = gBrowser;
|
||||
if (selectedBrowser.browserId !== this._currentBrowser.browserId) {
|
||||
this.showMediaControls();
|
||||
}
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
this.activateMediaControls(event.target.browsingContext.mediaController, event.target);
|
||||
});
|
||||
|
||||
window.addEventListener('DOMAudioPlaybackStopped', () => this.updateMuteState());
|
||||
}
|
||||
|
||||
onTabDiscardedOrClosed(event) {
|
||||
const linkedBrowser = event.target.linkedBrowser;
|
||||
if (!linkedBrowser?.browsingContext?.mediaController) return;
|
||||
this.deinitMediaController(
|
||||
linkedBrowser.browsingContext.mediaController,
|
||||
true,
|
||||
linkedBrowser.browserId === this._currentBrowser?.browserId,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
async deinitMediaController(mediaController, shouldForget = true, shouldOverride = true, shouldHide = true) {
|
||||
if (!mediaController) return;
|
||||
|
||||
const retrievedMediaController = this.mediaControllersMap.get(mediaController.id);
|
||||
|
||||
if (shouldForget) {
|
||||
mediaController.removeEventListener('pictureinpicturemodechange', this.onPipModeChange);
|
||||
mediaController.removeEventListener('positionstatechange', this.onPositionstateChange);
|
||||
mediaController.removeEventListener('playbackstatechange', this.onPlaybackstateChange);
|
||||
mediaController.removeEventListener('supportedkeyschange', this.onSupportedKeysChange);
|
||||
mediaController.removeEventListener('metadatachange', this.onMetadataChange);
|
||||
mediaController.removeEventListener('deactivated', this.onDeactivated);
|
||||
|
||||
this.mediaControllersMap.delete(mediaController.id);
|
||||
this.pipEligibilityMap.delete(retrievedMediaController?.browser?.browserId);
|
||||
}
|
||||
|
||||
if (shouldOverride) {
|
||||
this._currentMediaController = null;
|
||||
this._currentBrowser = null;
|
||||
|
||||
if (this._mediaUpdateInterval) {
|
||||
clearInterval(this._mediaUpdateInterval);
|
||||
this._mediaUpdateInterval = null;
|
||||
}
|
||||
|
||||
if (shouldHide) await this.hideMediaControls();
|
||||
this.mediaControlBar.removeAttribute('muted');
|
||||
this.mediaControlBar.classList.remove('playing');
|
||||
}
|
||||
}
|
||||
|
||||
hideMediaControls() {
|
||||
if (this.mediaControlBar.hasAttribute('hidden')) return;
|
||||
|
||||
return gZenUIManager.motion
|
||||
.animate(
|
||||
this.mediaControlBar,
|
||||
{
|
||||
opacity: [1, 0],
|
||||
y: [0, 10],
|
||||
},
|
||||
{
|
||||
duration: 0.1,
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
this.mediaControlBar.setAttribute('hidden', 'true');
|
||||
gZenUIManager.updateTabsToolbar();
|
||||
gZenUIManager.restoreScrollbarState();
|
||||
});
|
||||
}
|
||||
|
||||
showMediaControls() {
|
||||
if (!this._currentMediaController) return;
|
||||
|
||||
if (this._currentMediaController.isBeingUsedInPIPModeOrFullscreen) return this.hideMediaControls();
|
||||
if (!this.mediaControlBar.hasAttribute('hidden')) return;
|
||||
|
||||
this.updatePipButton();
|
||||
const mediaInfoElements = [this.mediaTitle, this.mediaArtist];
|
||||
for (const element of mediaInfoElements) {
|
||||
element.removeAttribute('overflow'); // So we can properly recalculate the overflow
|
||||
}
|
||||
|
||||
this.mediaControlBar.removeAttribute('hidden');
|
||||
window.requestAnimationFrame(() => {
|
||||
this.mediaControlBar.style.height =
|
||||
this.mediaControlBar.querySelector('toolbaritem').getBoundingClientRect().height + 'px';
|
||||
this.mediaControlBar.style.opacity = 0;
|
||||
gZenUIManager.updateTabsToolbar();
|
||||
gZenUIManager.restoreScrollbarState();
|
||||
gZenUIManager.motion.animate(
|
||||
this.mediaControlBar,
|
||||
{
|
||||
opacity: [0, 1],
|
||||
y: [10, 0],
|
||||
},
|
||||
{}
|
||||
);
|
||||
this.addLabelOverflows(mediaInfoElements);
|
||||
});
|
||||
}
|
||||
|
||||
addLabelOverflows(elements) {
|
||||
for (const element of elements) {
|
||||
const parent = element.parentElement;
|
||||
if (element.scrollWidth > parent.clientWidth) {
|
||||
element.setAttribute('overflow', '');
|
||||
} else {
|
||||
element.removeAttribute('overflow');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setupMediaController(mediaController, browser) {
|
||||
this._currentMediaController = mediaController;
|
||||
this._currentBrowser = browser;
|
||||
|
||||
this.updatePipButton();
|
||||
}
|
||||
|
||||
setupMediaControlUI(metadata, positionState) {
|
||||
this.updatePipButton();
|
||||
|
||||
if (!this.mediaControlBar.classList.contains('playing') && this._currentMediaController.isPlaying) {
|
||||
this.mediaControlBar.classList.add('playing');
|
||||
}
|
||||
|
||||
const iconURL = this._currentBrowser.mIconURL || `page-icon:${this._currentBrowser.currentURI.spec}`;
|
||||
this.mediaFocusButton.style.listStyleImage = `url(${iconURL})`;
|
||||
|
||||
this.mediaTitle.textContent = metadata.title || '';
|
||||
this.mediaArtist.textContent = metadata.artist || '';
|
||||
|
||||
gZenUIManager.updateTabsToolbar();
|
||||
gZenUIManager.restoreScrollbarState();
|
||||
|
||||
this._currentPosition = positionState.position;
|
||||
this._currentDuration = positionState.duration;
|
||||
this._currentPlaybackRate = positionState.playbackRate;
|
||||
|
||||
this.updateMediaPosition();
|
||||
|
||||
for (const key of this.supportedKeys) {
|
||||
const button = this.mediaControlBar.querySelector(`#zen-media-${key}-button`);
|
||||
button.disabled = !this._currentMediaController.supportedKeys.includes(key);
|
||||
}
|
||||
}
|
||||
|
||||
activateMediaControls(mediaController, browser) {
|
||||
this.updateMuteState();
|
||||
this.switchController();
|
||||
|
||||
if (!mediaController.isActive || this._currentBrowser?.browserId === browser.browserId) return;
|
||||
|
||||
const metadata = mediaController.getMetadata();
|
||||
const positionState = mediaController.getPositionState();
|
||||
this.mediaControllersMap.set(mediaController.id, {
|
||||
controller: mediaController,
|
||||
browser,
|
||||
position: positionState.position,
|
||||
duration: positionState.duration,
|
||||
playbackRate: positionState.playbackRate,
|
||||
lastUpdated: Date.now(),
|
||||
});
|
||||
|
||||
if (!this._currentBrowser) {
|
||||
this.setupMediaController(mediaController, browser);
|
||||
this.setupMediaControlUI(metadata, positionState);
|
||||
}
|
||||
|
||||
mediaController.addEventListener('pictureinpicturemodechange', this.onPipModeChange);
|
||||
mediaController.addEventListener('positionstatechange', this.onPositionstateChange);
|
||||
mediaController.addEventListener('playbackstatechange', this.onPlaybackstateChange);
|
||||
mediaController.addEventListener('supportedkeyschange', this.onSupportedKeysChange);
|
||||
mediaController.addEventListener('metadatachange', this.onMetadataChange);
|
||||
mediaController.addEventListener('deactivated', this.onDeactivated);
|
||||
}
|
||||
|
||||
updatePipEligibility(browser, isEligible) {
|
||||
this.pipEligibilityMap.set(browser.browserId, isEligible);
|
||||
}
|
||||
|
||||
_onDeactivated(event) {
|
||||
this.deinitMediaController(event.target, true, event.target.id === this._currentMediaController.id, true);
|
||||
this.switchController();
|
||||
}
|
||||
|
||||
_onPlaybackstateChange() {
|
||||
if (this._currentMediaController?.isPlaying) {
|
||||
this.mediaControlBar.classList.add('playing');
|
||||
} else {
|
||||
this.switchController();
|
||||
this.mediaControlBar.classList.remove('playing');
|
||||
}
|
||||
}
|
||||
|
||||
_onSupportedKeysChange(event) {
|
||||
if (event.target.id !== this._currentMediaController?.id) return;
|
||||
for (const key of this.supportedKeys) {
|
||||
const button = this.mediaControlBar.querySelector(`#zen-media-${key}-button`);
|
||||
button.disabled = !event.target.supportedKeys.includes(key);
|
||||
}
|
||||
}
|
||||
|
||||
_onPositionstateChange(event) {
|
||||
const mediaController = this.mediaControllersMap.get(event.target.id);
|
||||
this.mediaControllersMap.set(event.target.id, {
|
||||
...mediaController,
|
||||
position: event.position,
|
||||
duration: event.duration,
|
||||
playbackRate: event.playbackRate,
|
||||
lastUpdated: Date.now(),
|
||||
});
|
||||
|
||||
if (event.target.id !== this._currentMediaController?.id) return;
|
||||
|
||||
this._currentPosition = event.position;
|
||||
this._currentDuration = event.duration;
|
||||
this._currentPlaybackRate = event.playbackRate;
|
||||
|
||||
this.updateMediaPosition();
|
||||
}
|
||||
|
||||
switchController(force = false) {
|
||||
let timeout = 3000;
|
||||
|
||||
if (this._controllerSwitchTimeout) {
|
||||
clearTimeout(this._controllerSwitchTimeout);
|
||||
this._controllerSwitchTimeout = null;
|
||||
}
|
||||
|
||||
if (this.mediaControllersMap.size === 1) timeout = 0;
|
||||
this._controllerSwitchTimeout = setTimeout(() => {
|
||||
if (!this._currentMediaController?.isPlaying || force) {
|
||||
const nextController = Array.from(this.mediaControllersMap.values())
|
||||
.filter(
|
||||
(ctrl) =>
|
||||
ctrl.controller.isPlaying &&
|
||||
gBrowser.selectedBrowser.browserId !== ctrl.browser.browserId &&
|
||||
ctrl.controller.id !== this._currentMediaController?.id
|
||||
)
|
||||
.sort((a, b) => b.lastUpdated - a.lastUpdated)
|
||||
.shift();
|
||||
|
||||
if (nextController) {
|
||||
this.deinitMediaController(this._currentMediaController, false, true).then(() => {
|
||||
this.setupMediaController(nextController.controller, nextController.browser);
|
||||
const elapsedTime = Math.floor((Date.now() - nextController.lastUpdated) / 1000);
|
||||
|
||||
this.setupMediaControlUI(nextController.controller.getMetadata(), {
|
||||
position: nextController.position + (nextController.controller.isPlaying ? elapsedTime : 0),
|
||||
duration: nextController.duration,
|
||||
playbackRate: nextController.playbackRate,
|
||||
});
|
||||
|
||||
this.showMediaControls();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this._controllerSwitchTimeout = null;
|
||||
}, timeout);
|
||||
}
|
||||
|
||||
updateMediaPosition() {
|
||||
if (this._mediaUpdateInterval) {
|
||||
clearInterval(this._mediaUpdateInterval);
|
||||
this._mediaUpdateInterval = null;
|
||||
}
|
||||
|
||||
if (this._currentDuration >= 900_000) return this.mediaControlBar.setAttribute('media-position-hidden', 'true');
|
||||
else this.mediaControlBar.removeAttribute('media-position-hidden');
|
||||
|
||||
if (!this._currentDuration) return;
|
||||
|
||||
this.mediaCurrentTime.textContent = this.formatSecondsToTime(this._currentPosition);
|
||||
this.mediaDuration.textContent = this.formatSecondsToTime(this._currentDuration);
|
||||
this.mediaProgressBar.value = (this._currentPosition / this._currentDuration) * 100;
|
||||
|
||||
this._mediaUpdateInterval = setInterval(() => {
|
||||
if (this._currentMediaController?.isPlaying) {
|
||||
this._currentPosition += 1 * this._currentPlaybackRate;
|
||||
if (this._currentPosition > this._currentDuration) {
|
||||
this._currentPosition = this._currentDuration;
|
||||
}
|
||||
this.mediaCurrentTime.textContent = this.formatSecondsToTime(this._currentPosition);
|
||||
this.mediaProgressBar.value = (this._currentPosition / this._currentDuration) * 100;
|
||||
} else {
|
||||
clearInterval(this._mediaUpdateInterval);
|
||||
this._mediaUpdateInterval = null;
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
formatSecondsToTime(seconds) {
|
||||
if (!seconds || isNaN(seconds)) return '0:00';
|
||||
|
||||
const totalSeconds = Math.max(0, Math.ceil(seconds));
|
||||
const hours = Math.floor(totalSeconds / 3600);
|
||||
const minutes = Math.floor((totalSeconds % 3600) / 60).toString();
|
||||
const secs = (totalSeconds % 60).toString();
|
||||
|
||||
if (hours > 0) {
|
||||
return `${hours}:${minutes.padStart(2, '0')}:${secs.padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
return `${minutes}:${secs.padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
_onMetadataChange(event) {
|
||||
if (event.target.id !== this._currentMediaController?.id) return;
|
||||
this.updatePipButton();
|
||||
|
||||
const metadata = event.target.getMetadata();
|
||||
this.mediaTitle.textContent = metadata.title || '';
|
||||
this.mediaArtist.textContent = metadata.artist || '';
|
||||
|
||||
const mediaInfoElements = [this.mediaTitle, this.mediaArtist];
|
||||
for (const element of mediaInfoElements) {
|
||||
element.removeAttribute('overflow');
|
||||
}
|
||||
|
||||
this.addLabelOverflows(mediaInfoElements);
|
||||
}
|
||||
|
||||
_onPictureInPictureModeChange(event) {
|
||||
if (event.target.id !== this._currentMediaController?.id) return;
|
||||
if (event.target.isBeingUsedInPIPModeOrFullscreen) {
|
||||
this.hideMediaControls();
|
||||
this.mediaControlBar.setAttribute('pip', '');
|
||||
} else {
|
||||
const { selectedBrowser } = gBrowser;
|
||||
if (selectedBrowser.browserId !== this._currentBrowser.browserId) {
|
||||
this.showMediaControls();
|
||||
}
|
||||
|
||||
this.mediaControlBar.removeAttribute('pip');
|
||||
}
|
||||
}
|
||||
|
||||
onMediaPlayPrev() {
|
||||
if (this._currentMediaController?.supportedKeys.includes('previoustrack')) {
|
||||
this._currentMediaController.prevTrack();
|
||||
}
|
||||
}
|
||||
|
||||
onMediaPlayNext() {
|
||||
if (this._currentMediaController?.supportedKeys.includes('nexttrack')) {
|
||||
this._currentMediaController.nextTrack();
|
||||
}
|
||||
}
|
||||
|
||||
onMediaSeekDrag(event) {
|
||||
this._currentMediaController?.pause();
|
||||
const newTime = (event.target.value / 100) * this._currentDuration;
|
||||
this.mediaCurrentTime.textContent = this.formatSecondsToTime(newTime);
|
||||
}
|
||||
|
||||
onMediaSeekComplete(event) {
|
||||
const newPosition = (event.target.value / 100) * this._currentDuration;
|
||||
if (this._currentMediaController?.supportedKeys.includes('seekto')) {
|
||||
this._currentMediaController.seekTo(newPosition);
|
||||
this._currentMediaController.play();
|
||||
}
|
||||
}
|
||||
|
||||
onMediaFocus() {
|
||||
if (!this._currentBrowser) return;
|
||||
this._currentMediaController?.focus();
|
||||
}
|
||||
|
||||
onMediaMute() {
|
||||
if (!this.mediaControlBar.hasAttribute('muted')) {
|
||||
this._currentBrowser.mute();
|
||||
this.mediaControlBar.setAttribute('muted', '');
|
||||
} else {
|
||||
this._currentBrowser.unmute();
|
||||
this.mediaControlBar.removeAttribute('muted');
|
||||
}
|
||||
}
|
||||
|
||||
onMediaToggle() {
|
||||
if (this.mediaControlBar.classList.contains('playing')) {
|
||||
this._currentMediaController?.pause();
|
||||
} else {
|
||||
this._currentMediaController?.play();
|
||||
}
|
||||
}
|
||||
|
||||
onControllerClose() {
|
||||
this._currentMediaController?.pause();
|
||||
this.switchController(true);
|
||||
this.deinitMediaController(this._currentMediaController);
|
||||
}
|
||||
|
||||
onMediaPip() {
|
||||
this._currentBrowser.browsingContext.currentWindowGlobal
|
||||
.getActor('PictureInPictureLauncher')
|
||||
.sendAsyncMessage('PictureInPicture:KeyToggle');
|
||||
}
|
||||
|
||||
updateMuteState() {
|
||||
if (!this._currentBrowser) return;
|
||||
if (this._currentBrowser._audioMuted) {
|
||||
this.mediaControlBar.setAttribute('muted', '');
|
||||
} else {
|
||||
this.mediaControlBar.removeAttribute('muted');
|
||||
}
|
||||
}
|
||||
|
||||
updatePipButton() {
|
||||
if (!this._currentBrowser) return;
|
||||
|
||||
const isPipEligible = this.pipEligibilityMap.get(this._currentBrowser.browserId);
|
||||
if (isPipEligible) this.mediaControlBar.setAttribute('can-pip', '');
|
||||
else this.mediaControlBar.removeAttribute('can-pip');
|
||||
}
|
||||
}
|
||||
|
||||
window.gZenMediaController = new ZenMediaController();
|
@@ -1,428 +0,0 @@
|
||||
{
|
||||
const ZEN_RICE_API = Services.prefs.getStringPref('zen.rice.api.url', '');
|
||||
|
||||
class ZenRiceCollector {
|
||||
constructor() {}
|
||||
|
||||
clear() {
|
||||
this._userChrome = null;
|
||||
this._userContent = null;
|
||||
this._enabledMods = null;
|
||||
this._preferences = null;
|
||||
this._workspaceThemes = null;
|
||||
}
|
||||
|
||||
async gatherAll({
|
||||
userUserChrome = true,
|
||||
userContent = true,
|
||||
enabledMods = true,
|
||||
preferences = true,
|
||||
modPrefs = true,
|
||||
workspaceThemes = true,
|
||||
} = {}) {
|
||||
this.clear();
|
||||
// Get the mods first, as they may be needed for the preferences
|
||||
if (enabledMods) {
|
||||
await this.gatherEnabledMods();
|
||||
}
|
||||
await Promise.all([
|
||||
userUserChrome && this.gatherUserChrome(),
|
||||
userContent && this.gatherUserContent(),
|
||||
preferences && this.gatherPreferences({ modPrefs }),
|
||||
workspaceThemes && this.gatherWorkspaceThemes(),
|
||||
]);
|
||||
}
|
||||
|
||||
get profileDir() {
|
||||
return PathUtils.profileDir;
|
||||
}
|
||||
|
||||
async gatherUserChrome() {
|
||||
try {
|
||||
const path = PathUtils.join(this.profileDir, 'chrome', 'userChrome.css');
|
||||
this._userChrome = await IOUtils.readUTF8(path);
|
||||
} catch (e) {
|
||||
console.warn('[ZenRiceCollector]: Error reading userChrome.css: ', e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async gatherUserContent() {
|
||||
try {
|
||||
const path = PathUtils.join(this.profileDir, 'chrome', 'userContent.css');
|
||||
this._userContent = await IOUtils.readUTF8(path);
|
||||
} catch (e) {
|
||||
console.warn('[ZenRiceCollector]: Error reading userContent.css: ', e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async gatherEnabledMods() {
|
||||
const activeThemes = await gZenThemesImporter.getEnabledThemes();
|
||||
if (activeThemes.length === 0) {
|
||||
return;
|
||||
}
|
||||
this._enabledMods = activeThemes;
|
||||
}
|
||||
|
||||
_getThemePrefValue(theme, pref) {
|
||||
if (pref.type === 'checkbox') {
|
||||
return Services.prefs.getBoolPref(pref.property);
|
||||
}
|
||||
return Services.prefs.getStringPref(pref.property);
|
||||
}
|
||||
|
||||
async gatherPreferences({ modPrefs = true } = {}) {
|
||||
this._preferences = {};
|
||||
if (modPrefs && this._enabledMods) {
|
||||
for (const theme of this._enabledMods) {
|
||||
const prefs = await ZenThemesCommon.getThemePreferences(theme);
|
||||
for (const pref of prefs) {
|
||||
this._preferences[pref.property] = this._getThemePrefValue(theme, pref);
|
||||
}
|
||||
}
|
||||
}
|
||||
const boolPrefsToCollect = [
|
||||
'zen.view.use-single-toolbar',
|
||||
'zen.view.sidebar-expanded',
|
||||
'zen.tabs.vertical.right-side',
|
||||
'zen.view.experimental-no-window-controls',
|
||||
'zen.view.hide-window-controls',
|
||||
...(gZenOperatingSystemCommonUtils.currentOperatingSystem === 'windows' ? ['widget.windows.mica'] : []),
|
||||
...(gZenOperatingSystemCommonUtils.currentOperatingSystem === 'macos'
|
||||
? ['widget.macos.titlebar-blend-mode.behind-window']
|
||||
: []),
|
||||
];
|
||||
const stringPrefsToCollect = ['browser.uiCustomization.state'];
|
||||
for (const pref of boolPrefsToCollect) {
|
||||
this._preferences[pref] = Services.prefs.getBoolPref(pref);
|
||||
}
|
||||
for (const pref of stringPrefsToCollect) {
|
||||
this._preferences[pref] = Services.prefs.getStringPref(pref);
|
||||
}
|
||||
}
|
||||
|
||||
async gatherWorkspaceThemes() {
|
||||
const workspaces = (await ZenWorkspaces._workspaces()).workspaces;
|
||||
this._workspaceThemes = workspaces.map((w) => w.theme);
|
||||
}
|
||||
|
||||
async packRice(...args) {
|
||||
await this.gatherAll(...args);
|
||||
const rice = {
|
||||
userChrome: this._userChrome,
|
||||
userContent: this._userContent,
|
||||
enabledMods: this._enabledMods?.map((t) => t.id),
|
||||
preferences: this._preferences,
|
||||
workspaceThemes: this._workspaceThemes,
|
||||
};
|
||||
return rice;
|
||||
}
|
||||
}
|
||||
|
||||
class ZenRiceManager {
|
||||
constructor() {
|
||||
this._collector = new ZenRiceCollector();
|
||||
}
|
||||
|
||||
init() {}
|
||||
|
||||
get conffettiWrapper() {
|
||||
if (!this.confetti) {
|
||||
Services.scriptloader.loadSubScript('chrome://browser/content/zen-vendor/tsparticles.confetti.bundle.min.js', this);
|
||||
}
|
||||
return this.confetti;
|
||||
}
|
||||
|
||||
async packRice() {
|
||||
return await this._collector.packRice();
|
||||
}
|
||||
|
||||
get shareDialog() {
|
||||
if (this._shareDialog) {
|
||||
return this._shareDialog;
|
||||
}
|
||||
this._shareDialog = window.MozXULElement.parseXULToFragment(`
|
||||
<vbox id="zen-rice-share-dialog-overlay" hidden="true">
|
||||
<vbox id="zen-rice-share-dialog-notice">
|
||||
<h1 data-l10n-id="zen-rice-share-notice" />
|
||||
<p data-l10n-id="zen-rice-share-notice-description" />
|
||||
<html:moz-button-group class="panel-footer">
|
||||
<html:a href="https://docs.zen-browser.app/guides/" target="_blank" data-l10n-id="zen-learn-more-text" onclick="gZenThemePicker.riceManager.openLink(event)" />
|
||||
<button onclick="gZenThemePicker.riceManager.acceptNotice()" class="footer-button" data-l10n-id="zen-rice-share-accept" slot="primary" default="true" />
|
||||
</html:moz-button-group>
|
||||
</vbox>
|
||||
<vbox id="zen-rice-share-dialog" hidden="true">
|
||||
<html:img src="chrome://browser/content/zen-images/brand-header.svg" class="zen-rice-share-header" />
|
||||
<hbox class="zen-rice-share-content">
|
||||
<vbox id="zen-rice-share-first-form">
|
||||
<html:input type="text" data-l10n-id="zen-rice-share-name" id="zen-rice-share-name" oninput="gZenThemePicker.riceManager.validateShareDialog()" />
|
||||
<hbox class="zen-rice-share-author">
|
||||
<label data-l10n-id="zen-rice-share-author" />
|
||||
<html:input type="text" data-l10n-id="zen-rice-share-author-input" id="zen-rice-share-author" oninput="gZenThemePicker.riceManager.validateShareDialog();" />
|
||||
</hbox>
|
||||
<vbox zen-collapsed="true" id="zen-rice-share-options" onclick="gZenThemePicker.riceManager.toggleOptions(event)">
|
||||
<hbox class="options-header">
|
||||
<label data-l10n-id="zen-rice-share-include" />
|
||||
<image></image>
|
||||
</hbox>
|
||||
<checkbox data-l10n-id="zen-rice-share-include-userchrome" id="zen-rice-share-include-userchrome" />
|
||||
<checkbox data-l10n-id="zen-rice-share-include-usercontent" id="zen-rice-share-include-usercontent" />
|
||||
<checkbox data-l10n-id="zen-rice-share-include-mods" id="zen-rice-share-include-mods" />
|
||||
<vbox class="indent">
|
||||
<checkbox data-l10n-id="zen-rice-share-include-mod-prefs" id="zen-rice-share-include-mod-prefs" />
|
||||
</vbox>
|
||||
<checkbox data-l10n-id="zen-rice-share-include-preferences" id="zen-rice-share-include-preferences" />
|
||||
<checkbox data-l10n-id="zen-rice-share-include-workspace-themes" id="zen-rice-share-include-workspace-themes" />
|
||||
</vbox>
|
||||
<html:moz-button-group class="panel-footer">
|
||||
<button onclick="gZenThemePicker.riceManager.cancel()" class="footer-button" data-l10n-id="zen-general-cancel" />
|
||||
<button onclick="gZenThemePicker.riceManager.submit()" class="footer-button" data-l10n-id="zen-rice-share-save" default="true" slot="primary" id="zen-rice-share-save" disabled="true" />
|
||||
</html:moz-button-group>
|
||||
</vbox>
|
||||
<vbox id="zen-rice-share-second-form" hidden="true">
|
||||
<hbox></hbox>
|
||||
<vbox id="zen-rice-share-error" hidden="true">
|
||||
<label data-l10n-id="zen-rice-share-error" />
|
||||
<button onclick="gZenThemePicker.riceManager.resetShareDialog()" data-l10n-id="zen-close-label" class="footer-button" />
|
||||
</vbox>
|
||||
</vbox>
|
||||
<vbox id="zen-rice-share-success" hidden="true">
|
||||
<h1 data-l10n-id="zen-rice-share-success" />
|
||||
<p data-l10n-id="zen-rice-share-succes-details" />
|
||||
<label data-l10n-id="zen-rice-share-success-link" />
|
||||
<html:input type="text" readonly="true" id="zen-rice-share-success-link" onclick="this.select()" />
|
||||
<html:moz-button-group class="panel-footer">
|
||||
<button onclick="gZenThemePicker.riceManager.resetShareDialog()" data-l10n-id="zen-close-label" class="footer-button" slot="primary" default="true" />
|
||||
</html:moz-button-group>
|
||||
</vbox>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</vbox>
|
||||
`);
|
||||
document.getElementById('zen-main-app-wrapper').appendChild(this._shareDialog);
|
||||
this._shareDialog = document.getElementById('zen-rice-share-dialog-overlay');
|
||||
return this._shareDialog;
|
||||
}
|
||||
|
||||
get hasAcceptedNotice() {
|
||||
return Services.prefs.getBoolPref('zen.rice.share.notice.accepted', false);
|
||||
}
|
||||
|
||||
set hasAcceptedNotice(value) {
|
||||
Services.prefs.setBoolPref('zen.rice.share.notice.accepted', value);
|
||||
}
|
||||
|
||||
openLink(event) {
|
||||
event.stopPropagation();
|
||||
this.cancel();
|
||||
gZenUIManager.openAndChangeToTab('https://docs.zen-browser.app/guides/');
|
||||
}
|
||||
|
||||
acceptNotice() {
|
||||
this.hasAcceptedNotice = true;
|
||||
const notice = document.getElementById('zen-rice-share-dialog-notice');
|
||||
notice.setAttribute('hidden', 'true');
|
||||
this.openShareDialog();
|
||||
}
|
||||
|
||||
toggleOptions(event) {
|
||||
if (event.originalTarget.closest('.options-header')) {
|
||||
const options = document.getElementById('zen-rice-share-options');
|
||||
options.setAttribute('zen-collapsed', options.getAttribute('zen-collapsed') === 'true' ? 'false' : 'true');
|
||||
}
|
||||
this.validateShareDialog();
|
||||
}
|
||||
|
||||
openShareDialog() {
|
||||
window.docShell.treeOwner.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIAppWindow).rollupAllPopups();
|
||||
const dialog = this.shareDialog;
|
||||
dialog.removeAttribute('hidden');
|
||||
|
||||
if (!this.hasAcceptedNotice) {
|
||||
const notice = document.getElementById('zen-rice-share-dialog-notice');
|
||||
notice.removeAttribute('hidden');
|
||||
return;
|
||||
}
|
||||
|
||||
document.getElementById('zen-rice-share-dialog').removeAttribute('hidden');
|
||||
document.getElementById('zen-rice-share-dialog-notice').setAttribute('hidden', 'true');
|
||||
document.getElementById('zen-rice-share-name').focus();
|
||||
|
||||
// Initialize the dialog with the current values
|
||||
this.validateShareDialog();
|
||||
}
|
||||
|
||||
resetShareDialog() {
|
||||
const dialog = this.shareDialog;
|
||||
dialog.setAttribute('hidden', 'true');
|
||||
document.getElementById('zen-rice-share-dialog').removeAttribute('animate');
|
||||
document.getElementById('zen-rice-share-name').value = '';
|
||||
document.getElementById('zen-rice-share-author').value = '';
|
||||
document.getElementById('zen-rice-share-save').disabled = true;
|
||||
document.getElementById('zen-rice-share-first-form').removeAttribute('fade-out');
|
||||
document.getElementById('zen-rice-share-second-form').setAttribute('hidden', 'true');
|
||||
document.getElementById('zen-rice-share-second-form').removeAttribute('fade-out');
|
||||
document.getElementById('zen-rice-share-error').setAttribute('hidden', 'true');
|
||||
document.getElementById('zen-rice-share-success').setAttribute('hidden', 'true');
|
||||
document.getElementById('zen-rice-share-options').setAttribute('zen-collapsed', 'true');
|
||||
|
||||
// Remove confetti module from memory
|
||||
this.confetti = null;
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this.resetShareDialog();
|
||||
}
|
||||
|
||||
getAllowedRice() {
|
||||
return {
|
||||
userChrome: document.getElementById('zen-rice-share-include-userchrome').checked,
|
||||
userContent: document.getElementById('zen-rice-share-include-usercontent').checked,
|
||||
mods: document.getElementById('zen-rice-share-include-mods').checked,
|
||||
modPrefs: document.getElementById('zen-rice-share-include-mod-prefs').checked,
|
||||
preferences: document.getElementById('zen-rice-share-include-preferences').checked,
|
||||
workspaceThemes: document.getElementById('zen-rice-share-include-workspace-themes').checked,
|
||||
};
|
||||
}
|
||||
|
||||
get userAgent() {
|
||||
return `ZenBrowser/${Services.appinfo.version} (${gZenOperatingSystemCommonUtils.currentOperatingSystem})`;
|
||||
}
|
||||
|
||||
canShareRice() {
|
||||
const allowedRice = this.getAllowedRice();
|
||||
const modsPrefs = document.getElementById('zen-rice-share-include-mod-prefs');
|
||||
// remove "share mod prefs" if mods are not included
|
||||
if (!allowedRice.mods) {
|
||||
allowedRice.modPrefs = false;
|
||||
modsPrefs.disabled = true;
|
||||
}
|
||||
modsPrefs.disabled = !allowedRice.mods;
|
||||
return Object.values(allowedRice).some((v) => v);
|
||||
}
|
||||
|
||||
validateShareDialog() {
|
||||
const saveButton = document.getElementById('zen-rice-share-save');
|
||||
const authorInput = document.getElementById('zen-rice-share-author');
|
||||
const input = document.getElementById('zen-rice-share-name');
|
||||
saveButton.disabled =
|
||||
!this.canShareRice() ||
|
||||
input.value.trim().length < 3 ||
|
||||
input.value.trim().length > 30 ||
|
||||
authorInput.value.trim().length < 3 ||
|
||||
authorInput.value.trim().length > 15;
|
||||
}
|
||||
|
||||
async submit() {
|
||||
const firstForm = document.getElementById('zen-rice-share-first-form');
|
||||
const secondForm = document.getElementById('zen-rice-share-second-form');
|
||||
firstForm.setAttribute('fade-out', 'true');
|
||||
secondForm.removeAttribute('hidden');
|
||||
await this._submit();
|
||||
}
|
||||
|
||||
async _submit() {
|
||||
const allowedRice = this.getAllowedRice();
|
||||
const rice = await this._collector.packRice(allowedRice);
|
||||
const name = document.getElementById('zen-rice-share-name').value;
|
||||
const author = document.getElementById('zen-rice-share-author').value;
|
||||
const response = await this._sendRice({ name, author, rice });
|
||||
if (response) {
|
||||
this.showSuccessDialog(response);
|
||||
}
|
||||
}
|
||||
|
||||
async _sendRice({ name, author, rice }) {
|
||||
const headers = new Headers();
|
||||
headers.append('X-Zen-Rice-Name', name);
|
||||
headers.append('X-Zen-Rice-Author', author);
|
||||
headers.append('User-Agent', this.userAgent);
|
||||
headers.append('Content-Type', 'application/json');
|
||||
headers.append('Accept', 'application/json');
|
||||
let response;
|
||||
try {
|
||||
response = await fetch(`${ZEN_RICE_API}/rices`, {
|
||||
method: 'POST',
|
||||
headers,
|
||||
body: JSON.stringify(rice),
|
||||
});
|
||||
} catch (e) {
|
||||
this.showErrorMessage('An error occurred while sharing your rice. Please try again later.');
|
||||
console.error(e);
|
||||
return null;
|
||||
}
|
||||
// Here, response will never be a null object
|
||||
return await this._verifyResponse(response);
|
||||
}
|
||||
|
||||
async _verifyResponse(response) {
|
||||
const json = await response.json();
|
||||
if (!response.ok) {
|
||||
const message = json.message || 'An error occurred while sharing your rice.';
|
||||
this.showErrorMessage(message);
|
||||
console.error(json);
|
||||
return null;
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
showErrorMessage(message) {
|
||||
const errorBox = document.getElementById('zen-rice-share-error');
|
||||
errorBox.removeAttribute('hidden');
|
||||
errorBox.querySelector('label').textContent = message;
|
||||
}
|
||||
|
||||
showSuccessDialog(riceInfo) {
|
||||
const { slug, token } = riceInfo;
|
||||
// 'token' is like some sort of password to edit the rice, do NOT expose it
|
||||
setTimeout(() => {
|
||||
document.getElementById('zen-rice-share-dialog').setAttribute('animate', 'true');
|
||||
const successBox = document.getElementById('zen-rice-share-success');
|
||||
document.getElementById('zen-rice-share-second-form').setAttribute('fade-out', 'true');
|
||||
successBox.removeAttribute('hidden');
|
||||
const link = document.getElementById('zen-rice-share-success-link');
|
||||
link.value = `${ZEN_RICE_API}/rices/${slug}`;
|
||||
this.showConffetti();
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
showConffetti() {
|
||||
const end = Date.now() + 2500;
|
||||
function frame() {
|
||||
this.conffettiWrapper({
|
||||
angle: 135,
|
||||
spread: 55,
|
||||
particleCount: 5,
|
||||
startVelocity: 55,
|
||||
origin: { y: 0.6 },
|
||||
});
|
||||
this.conffettiWrapper({
|
||||
angle: 45,
|
||||
spread: 55,
|
||||
particleCount: 5,
|
||||
startVelocity: 55,
|
||||
origin: { y: 0.6 },
|
||||
});
|
||||
this.conffettiWrapper({
|
||||
angle: 90,
|
||||
spread: 55,
|
||||
particleCount: 5,
|
||||
startVelocity: 55,
|
||||
origin: { y: 0.6 },
|
||||
});
|
||||
if (Date.now() < end) {
|
||||
requestAnimationFrame(frame.bind(this));
|
||||
}
|
||||
}
|
||||
frame.call(this);
|
||||
}
|
||||
|
||||
openRicePage({ name, id, author }) {
|
||||
console.log('Opening rice page: ', name, id, author);
|
||||
gBrowser.removeTab(gBrowser.selectedTab);
|
||||
}
|
||||
}
|
||||
|
||||
window.ZenRiceManager = ZenRiceManager;
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += [
|
||||
"tests/browser.toml",
|
||||
]
|
||||
|
||||
FINAL_TARGET_FILES.actors += [
|
||||
"actors/ZenGlanceChild.sys.mjs",
|
||||
"actors/ZenGlanceParent.sys.mjs",
|
||||
"actors/ZenThemeMarketplaceChild.sys.mjs",
|
||||
"actors/ZenThemeMarketplaceParent.sys.mjs",
|
||||
]
|
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/components/customizableui/CustomizableUI.sys.mjs b/browser/components/customizableui/CustomizableUI.sys.mjs
|
||||
index 9392b42a1de7310719a6cc8aaf11bd857e8fa69a..24dc9acd733ae401f8cdfb2351a7275d16ee46c8 100644
|
||||
index 9392b42a1de7310719a6cc8aaf11bd857e8fa69a..1c5b80678fc3a4d17b0632a765b8182d88986bcc 100644
|
||||
--- a/browser/components/customizableui/CustomizableUI.sys.mjs
|
||||
+++ b/browser/components/customizableui/CustomizableUI.sys.mjs
|
||||
@@ -13,6 +13,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
||||
@@ -188,13 +188,12 @@ index 9392b42a1de7310719a6cc8aaf11bd857e8fa69a..24dc9acd733ae401f8cdfb2351a7275d
|
||||
}
|
||||
child.removeAttribute("cui-anchorid");
|
||||
child.removeAttribute("overflowedItem");
|
||||
@@ -7186,6 +7190,9 @@ class OverflowableToolbar {
|
||||
* @param {MouseEvent} aEvent the click event.
|
||||
*/
|
||||
#onClickDefaultListButton(aEvent) {
|
||||
+ if (aEvent.view.gZenVerticalTabsManager._hasSetSingleToolbar && this.#toolbar.id == 'nav-bar') {
|
||||
+ return;
|
||||
+ }
|
||||
if (this.#defaultListButton.open) {
|
||||
this.#defaultListButton.open = false;
|
||||
lazy.PanelMultiView.hidePopup(this.#defaultListPanel);
|
||||
@@ -7369,7 +7373,7 @@ class OverflowableToolbar {
|
||||
break;
|
||||
}
|
||||
case "mousedown": {
|
||||
- if (aEvent.button != 0) {
|
||||
+ if (aEvent.button != 0 || this.#toolbar.id == "zen-sidebar-top-buttons") { // Fix https://github.com/zen-browser/desktop/issues/7718
|
||||
break;
|
||||
}
|
||||
if (aEvent.target == this.#defaultListButton) {
|
||||
|
@@ -1024,4 +1024,9 @@ Preferences.addAll([
|
||||
type: 'bool',
|
||||
default: true,
|
||||
},
|
||||
{
|
||||
id: 'media.videocontrols.picture-in-picture.enabled',
|
||||
type: 'bool',
|
||||
default: true,
|
||||
},
|
||||
]);
|
||||
|
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/components/sessionstore/SessionStore.sys.mjs b/browser/components/sessionstore/SessionStore.sys.mjs
|
||||
index 6e2973abf428b110bfc553522723f327ee84c028..668cc147a1bf158bc42a7baf2a5549049d060899 100644
|
||||
index 6e2973abf428b110bfc553522723f327ee84c028..cf707b1aace542b4b42468bbaaffd047669c8c94 100644
|
||||
--- a/browser/components/sessionstore/SessionStore.sys.mjs
|
||||
+++ b/browser/components/sessionstore/SessionStore.sys.mjs
|
||||
@@ -3186,7 +3186,7 @@ var SessionStoreInternal = {
|
||||
@@ -11,15 +11,16 @@ index 6e2973abf428b110bfc553522723f327ee84c028..668cc147a1bf158bc42a7baf2a554904
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3895,6 +3895,7 @@ var SessionStoreInternal = {
|
||||
@@ -3895,6 +3895,8 @@ var SessionStoreInternal = {
|
||||
Math.min(tabState.index, tabState.entries.length)
|
||||
);
|
||||
tabState.pinned = false;
|
||||
+ tabState.zenEssential = undefined;
|
||||
+ tabState.zenEssential = false;
|
||||
+ tabState.zenPinnedId = null;
|
||||
|
||||
if (inBackground === false) {
|
||||
aWindow.gBrowser.selectedTab = newTab;
|
||||
@@ -5399,14 +5400,15 @@ var SessionStoreInternal = {
|
||||
@@ -5399,14 +5401,15 @@ var SessionStoreInternal = {
|
||||
}
|
||||
|
||||
let tabbrowser = aWindow.gBrowser;
|
||||
@@ -37,7 +38,7 @@ index 6e2973abf428b110bfc553522723f327ee84c028..668cc147a1bf158bc42a7baf2a554904
|
||||
continue;
|
||||
}
|
||||
let tabData = lazy.TabState.collect(tab, TAB_CUSTOM_VALUES.get(tab));
|
||||
@@ -5425,7 +5427,7 @@ var SessionStoreInternal = {
|
||||
@@ -5425,7 +5428,7 @@ var SessionStoreInternal = {
|
||||
// We don't store the Firefox View tab in Session Store, so if it was the last selected "tab" when
|
||||
// a window is closed, point to the first item in the tab strip instead (it will never be the Firefox View tab,
|
||||
// since it's only inserted into the tab strip after it's selected).
|
||||
@@ -46,7 +47,7 @@ index 6e2973abf428b110bfc553522723f327ee84c028..668cc147a1bf158bc42a7baf2a554904
|
||||
selectedIndex = 1;
|
||||
winData.title = tabbrowser.tabs[0].label;
|
||||
}
|
||||
@@ -5582,6 +5584,7 @@ var SessionStoreInternal = {
|
||||
@@ -5582,6 +5585,7 @@ var SessionStoreInternal = {
|
||||
winData.tabs,
|
||||
winData.groups ?? []
|
||||
);
|
||||
@@ -54,7 +55,7 @@ index 6e2973abf428b110bfc553522723f327ee84c028..668cc147a1bf158bc42a7baf2a554904
|
||||
this._log.debug(
|
||||
`restoreWindow, createTabsForSessionRestore returned ${tabs.length} tabs`
|
||||
);
|
||||
@@ -6130,8 +6133,23 @@ var SessionStoreInternal = {
|
||||
@@ -6130,8 +6134,23 @@ var SessionStoreInternal = {
|
||||
|
||||
// Most of tabData has been restored, now continue with restoring
|
||||
// attributes that may trigger external events.
|
||||
|
@@ -1,7 +1,16 @@
|
||||
diff --git a/browser/components/tabbrowser/content/browser-ctrlTab.js b/browser/components/tabbrowser/content/browser-ctrlTab.js
|
||||
index e5d16e605b7edf11fc9f52b93e415087b76398f1..40b6e29d26c7f8d692a2a9a7d924b289ec7a3d03 100644
|
||||
index 6753641cb579032306453be3f5054d7bc7661e8c..e0eda8d77637334ca30ee1842057cb43b4af2c21 100644
|
||||
--- a/browser/components/tabbrowser/content/browser-ctrlTab.js
|
||||
+++ b/browser/components/tabbrowser/content/browser-ctrlTab.js
|
||||
@@ -252,7 +252,7 @@ var ctrlTab = {
|
||||
},
|
||||
|
||||
get tabList() {
|
||||
- return this._recentlyUsedTabs;
|
||||
+ return this._recentlyUsedTabs.filter(tab => !tab.hasAttribute("pending"));
|
||||
},
|
||||
|
||||
init: function ctrlTab_init() {
|
||||
@@ -459,7 +459,7 @@ var ctrlTab = {
|
||||
// If the tab is hidden, don't add it to the list unless it's selected
|
||||
// (Normally hidden tabs would be unhidden when selected, but that doesn't
|
||||
|
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js
|
||||
index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344b86e2a7c 100644
|
||||
index 5f406ea5d09273c9b70b84eee24c6267f88692f8..be8740305b28cfc7752ad8f48ca94e69f8d324d1 100644
|
||||
--- a/browser/components/tabbrowser/content/tabbrowser.js
|
||||
+++ b/browser/components/tabbrowser/content/tabbrowser.js
|
||||
@@ -424,11 +424,67 @@
|
||||
@@ -151,16 +151,17 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
// If focus is on the old tab, move it to the new tab.
|
||||
if (activeEl == oldTab) {
|
||||
newTab.focus();
|
||||
@@ -1762,7 +1833,7 @@
|
||||
@@ -1762,7 +1833,8 @@
|
||||
}
|
||||
|
||||
_setTabLabel(aTab, aLabel, { beforeTabOpen, isContentTitle, isURL } = {}) {
|
||||
- if (!aLabel || aLabel.includes("about:reader?")) {
|
||||
+ gZenPinnedTabManager.onTabLabelChanged(aTab);
|
||||
+ if (!aLabel || aLabel.includes("about:reader?") || aTab.hasAttribute("zen-has-static-label")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1865,7 +1936,7 @@
|
||||
@@ -1865,7 +1937,7 @@
|
||||
newIndex = this.selectedTab._tPos + 1;
|
||||
}
|
||||
|
||||
@@ -169,7 +170,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
let browser;
|
||||
if (targetTab) {
|
||||
browser = this.getBrowserForTab(targetTab);
|
||||
@@ -2122,6 +2193,7 @@
|
||||
@@ -2122,6 +2194,7 @@
|
||||
uriIsAboutBlank,
|
||||
userContextId,
|
||||
skipLoad,
|
||||
@@ -177,7 +178,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
} = {}) {
|
||||
let b = document.createXULElement("browser");
|
||||
// Use the JSM global to create the permanentKey, so that if the
|
||||
@@ -2195,8 +2267,7 @@
|
||||
@@ -2195,8 +2268,7 @@
|
||||
// we use a different attribute name for this?
|
||||
b.setAttribute("name", name);
|
||||
}
|
||||
@@ -187,7 +188,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
b.setAttribute("transparent", "true");
|
||||
}
|
||||
|
||||
@@ -2373,7 +2444,7 @@
|
||||
@@ -2373,7 +2445,7 @@
|
||||
|
||||
let panel = this.getPanel(browser);
|
||||
let uniqueId = this._generateUniquePanelID();
|
||||
@@ -196,7 +197,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
aTab.linkedPanel = uniqueId;
|
||||
|
||||
// Inject the <browser> into the DOM if necessary.
|
||||
@@ -2432,8 +2503,8 @@
|
||||
@@ -2432,8 +2504,8 @@
|
||||
// If we transitioned from one browser to two browsers, we need to set
|
||||
// hasSiblings=false on both the existing browser and the new browser.
|
||||
if (this.tabs.length == 2) {
|
||||
@@ -207,7 +208,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
} else {
|
||||
aTab.linkedBrowser.browsingContext.hasSiblings = this.tabs.length > 1;
|
||||
}
|
||||
@@ -2655,6 +2726,7 @@
|
||||
@@ -2655,6 +2727,7 @@
|
||||
schemelessInput,
|
||||
hasValidUserGestureActivation = false,
|
||||
textDirectiveUserActivation = false,
|
||||
@@ -215,7 +216,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
} = {}
|
||||
) {
|
||||
// all callers of addTab that pass a params object need to pass
|
||||
@@ -2665,6 +2737,12 @@
|
||||
@@ -2665,6 +2738,12 @@
|
||||
);
|
||||
}
|
||||
|
||||
@@ -228,7 +229,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
if (!UserInteraction.running("browser.tabs.opening", window)) {
|
||||
UserInteraction.start("browser.tabs.opening", "initting", window);
|
||||
}
|
||||
@@ -2728,6 +2806,16 @@
|
||||
@@ -2728,6 +2807,16 @@
|
||||
noInitialLabel,
|
||||
skipBackgroundNotify,
|
||||
});
|
||||
@@ -245,7 +246,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
if (insertTab) {
|
||||
// insert the tab into the tab container in the correct position
|
||||
this._insertTabAtIndex(t, {
|
||||
@@ -2752,6 +2840,7 @@
|
||||
@@ -2752,6 +2841,7 @@
|
||||
initialBrowsingContextGroupId,
|
||||
openWindowInfo,
|
||||
skipLoad,
|
||||
@@ -253,7 +254,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
}));
|
||||
|
||||
if (focusUrlBar) {
|
||||
@@ -2871,6 +2960,9 @@
|
||||
@@ -2871,6 +2961,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,7 +264,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
// Additionally send pinned tab events
|
||||
if (pinned) {
|
||||
this._notifyPinnedStatus(t);
|
||||
@@ -2891,12 +2983,15 @@
|
||||
@@ -2891,12 +2984,15 @@
|
||||
* @param {string} [label=]
|
||||
* @returns {MozTabbrowserTabGroup}
|
||||
*/
|
||||
@@ -280,7 +281,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
return group;
|
||||
}
|
||||
|
||||
@@ -2937,6 +3032,7 @@
|
||||
@@ -2937,6 +3033,7 @@
|
||||
insertBefore = null,
|
||||
isUserCreated = false,
|
||||
telemetryUserCreateSource = "unknown",
|
||||
@@ -288,7 +289,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
} = {}
|
||||
) {
|
||||
if (!tabs?.length) {
|
||||
@@ -2951,7 +3047,12 @@
|
||||
@@ -2951,7 +3048,12 @@
|
||||
id = `${Date.now()}-${Math.round(Math.random() * 100)}`;
|
||||
}
|
||||
let group = this._createTabGroup(id, color, false, label);
|
||||
@@ -302,7 +303,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
group,
|
||||
insertBefore?.group ?? insertBefore
|
||||
);
|
||||
@@ -3268,6 +3369,7 @@
|
||||
@@ -3268,6 +3370,7 @@
|
||||
initialBrowsingContextGroupId,
|
||||
openWindowInfo,
|
||||
skipLoad,
|
||||
@@ -310,7 +311,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
}
|
||||
) {
|
||||
// If we don't have a preferred remote type, and we have a remote
|
||||
@@ -3331,6 +3433,7 @@
|
||||
@@ -3331,6 +3434,7 @@
|
||||
openWindowInfo,
|
||||
name,
|
||||
skipLoad,
|
||||
@@ -318,7 +319,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3509,6 +3612,27 @@
|
||||
@@ -3509,6 +3613,27 @@
|
||||
) {
|
||||
tabWasReused = true;
|
||||
tab = this.selectedTab;
|
||||
@@ -346,19 +347,12 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
if (!tabData.pinned) {
|
||||
this.unpinTab(tab);
|
||||
} else {
|
||||
@@ -3522,6 +3646,7 @@
|
||||
restoreTabsLazily && !select && !tabData.pinned;
|
||||
|
||||
let url = "about:blank";
|
||||
+ gZenPinnedTabManager.resetPinnedTabData(tabData);
|
||||
if (tabData.entries?.length) {
|
||||
let activeIndex = (tabData.index || tabData.entries.length) - 1;
|
||||
// Ensure the index is in bounds.
|
||||
@@ -3557,7 +3682,27 @@
|
||||
@@ -3557,8 +3682,28 @@
|
||||
skipLoad: true,
|
||||
preferredRemoteType,
|
||||
});
|
||||
-
|
||||
- if (select) {
|
||||
+ if (tabData.zenWorkspace) {
|
||||
+ tab.setAttribute("zen-workspace-id", tabData.zenWorkspace);
|
||||
+ }
|
||||
@@ -380,9 +374,10 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
+ if (tabData.zenPinnedEntry) {
|
||||
+ tab.setAttribute("zen-pinned-entry", tabData.zenPinnedEntry);
|
||||
+ }
|
||||
if (select) {
|
||||
+ if (select && !tabData.pinned) {
|
||||
tabToSelect = tab;
|
||||
}
|
||||
}
|
||||
@@ -3570,8 +3715,8 @@
|
||||
// inserted in the DOM. If the tab is not yet in the DOM,
|
||||
// just insert it in the right place from the start.
|
||||
@@ -468,7 +463,23 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
this.removeTabs(selectedTabs);
|
||||
}
|
||||
|
||||
@@ -4556,6 +4711,7 @@
|
||||
@@ -4450,6 +4605,7 @@
|
||||
skipGroupCheck = false,
|
||||
} = {}
|
||||
) {
|
||||
+ tabs = tabs.filter(tab => !tab.hasAttribute("zen-empty-tab"));
|
||||
// When 'closeWindowWithLastTab' pref is enabled, closing all tabs
|
||||
// can be considered equivalent to closing the window.
|
||||
if (
|
||||
@@ -4533,6 +4689,7 @@
|
||||
if (lastToClose) {
|
||||
this.removeTab(lastToClose, aParams);
|
||||
}
|
||||
+ gZenUIManager.onTabClose(undefined);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
@@ -4556,6 +4713,7 @@
|
||||
skipSessionStore,
|
||||
} = {}
|
||||
) {
|
||||
@@ -476,7 +487,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
if (UserInteraction.running("browser.tabs.opening", window)) {
|
||||
UserInteraction.finish("browser.tabs.opening", window);
|
||||
}
|
||||
@@ -4572,6 +4728,12 @@
|
||||
@@ -4572,6 +4730,12 @@
|
||||
TelemetryStopwatch.start("FX_TAB_CLOSE_TIME_NO_ANIM_MS", aTab);
|
||||
}
|
||||
|
||||
@@ -489,7 +500,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
// Handle requests for synchronously removing an already
|
||||
// asynchronously closing tab.
|
||||
if (!animate && aTab.closing) {
|
||||
@@ -4586,7 +4748,9 @@
|
||||
@@ -4586,7 +4750,9 @@
|
||||
// frame created for it (for example, by updating the visually selected
|
||||
// state).
|
||||
let tabWidth = window.windowUtils.getBoundsWithoutFlushing(aTab).width;
|
||||
@@ -500,7 +511,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
if (
|
||||
!this._beginRemoveTab(aTab, {
|
||||
closeWindowFastpath: true,
|
||||
@@ -4600,7 +4764,6 @@
|
||||
@@ -4600,7 +4766,6 @@
|
||||
TelemetryStopwatch.cancel("FX_TAB_CLOSE_TIME_NO_ANIM_MS", aTab);
|
||||
return;
|
||||
}
|
||||
@@ -508,7 +519,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
let lockTabSizing =
|
||||
!this.tabContainer.verticalMode &&
|
||||
!aTab.pinned &&
|
||||
@@ -4739,14 +4902,14 @@
|
||||
@@ -4739,14 +4904,14 @@
|
||||
!!this.tabsInCollapsedTabGroups.length;
|
||||
if (
|
||||
aTab.visible &&
|
||||
@@ -525,7 +536,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
|
||||
if (closeWindow) {
|
||||
// We've already called beforeunload on all the relevant tabs if we get here,
|
||||
@@ -4770,6 +4933,7 @@
|
||||
@@ -4770,6 +4935,7 @@
|
||||
|
||||
newTab = true;
|
||||
}
|
||||
@@ -533,7 +544,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
aTab._endRemoveArgs = [closeWindow, newTab];
|
||||
|
||||
// swapBrowsersAndCloseOther will take care of closing the window without animation.
|
||||
@@ -4810,9 +4974,7 @@
|
||||
@@ -4810,9 +4976,7 @@
|
||||
aTab._mouseleave();
|
||||
|
||||
if (newTab) {
|
||||
@@ -544,7 +555,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
} else {
|
||||
TabBarVisibility.update();
|
||||
}
|
||||
@@ -4941,6 +5103,8 @@
|
||||
@@ -4941,6 +5105,8 @@
|
||||
this.tabs[i]._tPos = i;
|
||||
}
|
||||
|
||||
@@ -553,7 +564,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
if (!this._windowIsClosing) {
|
||||
if (wasPinned) {
|
||||
this.tabContainer._positionPinnedTabs();
|
||||
@@ -5064,8 +5228,8 @@
|
||||
@@ -5064,8 +5230,8 @@
|
||||
return closedCount;
|
||||
}
|
||||
|
||||
@@ -564,7 +575,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
if (unloadBlocked) {
|
||||
return;
|
||||
}
|
||||
@@ -5159,7 +5323,7 @@
|
||||
@@ -5159,13 +5325,13 @@
|
||||
!excludeTabs.has(aTab.owner) &&
|
||||
Services.prefs.getBoolPref("browser.tabs.selectOwnerOnClose")
|
||||
) {
|
||||
@@ -573,7 +584,14 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
}
|
||||
|
||||
// Try to find a remaining tab that comes after the given tab
|
||||
@@ -5181,7 +5345,7 @@
|
||||
let remainingTabs = Array.prototype.filter.call(
|
||||
this.visibleTabs,
|
||||
- tab => !excludeTabs.has(tab)
|
||||
+ tab => !excludeTabs.has(tab) && ZenWorkspaces._shouldChangeToTab(tab)
|
||||
);
|
||||
|
||||
let tab = this.tabContainer.findNextTab(aTab, {
|
||||
@@ -5181,7 +5347,7 @@
|
||||
}
|
||||
|
||||
if (tab) {
|
||||
@@ -582,7 +600,16 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
}
|
||||
|
||||
// If no qualifying visible tab was found, see if there is a tab in
|
||||
@@ -5599,10 +5763,10 @@
|
||||
@@ -5202,7 +5368,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
- return tab;
|
||||
+ return ZenWorkspaces.findTabToBlur(tab);
|
||||
}
|
||||
|
||||
_blurTab(aTab) {
|
||||
@@ -5599,10 +5765,10 @@
|
||||
SessionStore.deleteCustomTabValue(aTab, "hiddenBy");
|
||||
}
|
||||
|
||||
@@ -595,7 +622,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
aTab.selected ||
|
||||
aTab.closing ||
|
||||
// Tabs that are sharing the screen, microphone or camera cannot be hidden.
|
||||
@@ -5838,7 +6002,7 @@
|
||||
@@ -5838,7 +6004,7 @@
|
||||
moveTabTo(aTab, aIndex, { forceStandaloneTab = false } = {}) {
|
||||
// Don't allow mixing pinned and unpinned tabs.
|
||||
if (aTab.pinned) {
|
||||
@@ -604,7 +631,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
} else {
|
||||
aIndex = Math.max(aIndex, this.pinnedTabCount);
|
||||
}
|
||||
@@ -5848,10 +6012,17 @@
|
||||
@@ -5848,10 +6014,17 @@
|
||||
|
||||
this.#handleTabMove(aTab, () => {
|
||||
let neighbor = this.tabs[aIndex];
|
||||
@@ -624,7 +651,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
neighbor.after(aTab);
|
||||
} else {
|
||||
this.tabContainer.insertBefore(aTab, neighbor);
|
||||
@@ -5901,13 +6072,22 @@
|
||||
@@ -5901,13 +6074,22 @@
|
||||
* Bug 1955388 - prevent pinned tabs from commingling with non-pinned tabs
|
||||
* when there are hidden tabs present
|
||||
*/
|
||||
@@ -648,7 +675,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
if (tab.pinned && this.tabContainer.verticalMode) {
|
||||
return this.tabContainer.verticalPinnedTabsContainer;
|
||||
}
|
||||
@@ -5937,7 +6117,7 @@
|
||||
@@ -5937,7 +6119,7 @@
|
||||
}
|
||||
|
||||
moveTabToGroup(aTab, aGroup) {
|
||||
@@ -657,7 +684,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
return;
|
||||
}
|
||||
if (aTab.group && aTab.group.id === aGroup.id) {
|
||||
@@ -5961,6 +6141,10 @@
|
||||
@@ -5961,6 +6143,10 @@
|
||||
|
||||
moveActionCallback();
|
||||
|
||||
@@ -668,7 +695,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
// Clear tabs cache after moving nodes because the order of tabs may have
|
||||
// changed.
|
||||
this.tabContainer._invalidateCachedTabs();
|
||||
@@ -6015,7 +6199,7 @@
|
||||
@@ -6015,7 +6201,7 @@
|
||||
createLazyBrowser,
|
||||
};
|
||||
|
||||
@@ -677,7 +704,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
if (aIndex < numPinned || (aTab.pinned && aIndex == numPinned)) {
|
||||
params.pinned = true;
|
||||
}
|
||||
@@ -6765,7 +6949,7 @@
|
||||
@@ -6765,7 +6951,7 @@
|
||||
// preventDefault(). It will still raise the window if appropriate.
|
||||
break;
|
||||
}
|
||||
@@ -686,7 +713,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
window.focus();
|
||||
aEvent.preventDefault();
|
||||
break;
|
||||
@@ -7671,6 +7855,7 @@
|
||||
@@ -7671,6 +7857,7 @@
|
||||
aWebProgress.isTopLevel
|
||||
) {
|
||||
this.mTab.setAttribute("busy", "true");
|
||||
@@ -694,7 +721,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
gBrowser._tabAttrModified(this.mTab, ["busy"]);
|
||||
this.mTab._notselectedsinceload = !this.mTab.selected;
|
||||
}
|
||||
@@ -8640,7 +8825,7 @@ var TabContextMenu = {
|
||||
@@ -8640,7 +8827,7 @@ var TabContextMenu = {
|
||||
);
|
||||
contextUnpinSelectedTabs.hidden =
|
||||
!this.contextTab.pinned || !this.multiselected;
|
||||
@@ -703,7 +730,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
// Move Tab items
|
||||
let contextMoveTabOptions = document.getElementById(
|
||||
"context_moveTabOptions"
|
||||
@@ -8674,7 +8859,7 @@ var TabContextMenu = {
|
||||
@@ -8674,7 +8861,7 @@ var TabContextMenu = {
|
||||
let isFirstTab =
|
||||
!this.contextTabs[0].group &&
|
||||
(this.contextTabs[0] == visibleTabs[0] ||
|
||||
@@ -712,7 +739,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..70cde185cb560a325f894c0ce79f1344
|
||||
contextMoveTabToStart.disabled = isFirstTab && allSelectedTabsAdjacent;
|
||||
|
||||
document.getElementById("context_openTabInWindow").disabled =
|
||||
@@ -8904,6 +9089,7 @@ var TabContextMenu = {
|
||||
@@ -8904,6 +9091,7 @@ var TabContextMenu = {
|
||||
if (this.contextTab.multiselected) {
|
||||
gBrowser.removeMultiSelectedTabs();
|
||||
} else {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/components/tabbrowser/content/tabs.js b/browser/components/tabbrowser/content/tabs.js
|
||||
index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f001dd4c3b1 100644
|
||||
index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..75a30478387494c06e5c8131f55ba5dc977c8415 100644
|
||||
--- a/browser/components/tabbrowser/content/tabs.js
|
||||
+++ b/browser/components/tabbrowser/content/tabs.js
|
||||
@@ -93,7 +93,7 @@
|
||||
@@ -101,7 +101,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
gBrowser.loadTabs(urls, {
|
||||
inBackground,
|
||||
replace,
|
||||
@@ -1276,13 +1294,23 @@
|
||||
@@ -1276,13 +1294,25 @@
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -114,6 +114,8 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
+ delete draggedTab._dragData;
|
||||
+ return;
|
||||
+ }
|
||||
+ } else if (dt.mozUserCancelled) {
|
||||
+ if (gZenViewSplitter._lastOpenedTab) gZenViewSplitter._lastOpenedTab._visuallySelected = false;
|
||||
+ }
|
||||
+
|
||||
+ this._finishMoveTogetherSelectedTabs(draggedTab);
|
||||
@@ -127,7 +129,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
) {
|
||||
delete draggedTab._dragData;
|
||||
return;
|
||||
@@ -1504,7 +1532,7 @@
|
||||
@@ -1504,7 +1534,7 @@
|
||||
}
|
||||
|
||||
get newTabButton() {
|
||||
@@ -136,7 +138,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
}
|
||||
|
||||
get verticalMode() {
|
||||
@@ -1524,29 +1552,41 @@
|
||||
@@ -1524,29 +1554,41 @@
|
||||
if (this.#allTabs) {
|
||||
return this.#allTabs;
|
||||
}
|
||||
@@ -186,7 +188,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1566,7 +1606,7 @@
|
||||
@@ -1566,7 +1608,7 @@
|
||||
*/
|
||||
get visibleTabs() {
|
||||
if (!this.#visibleTabs) {
|
||||
@@ -195,7 +197,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
}
|
||||
return this.#visibleTabs;
|
||||
}
|
||||
@@ -1601,23 +1641,18 @@
|
||||
@@ -1601,23 +1643,18 @@
|
||||
}
|
||||
|
||||
let elementIndex = 0;
|
||||
@@ -223,7 +225,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
let visibleTabsInGroup = child.tabs.filter(tab => tab.visible);
|
||||
visibleTabsInGroup.forEach(tab => {
|
||||
tab.elementIndex = elementIndex++;
|
||||
@@ -1627,10 +1662,7 @@
|
||||
@@ -1627,10 +1664,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,7 +237,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
|
||||
return this.#focusableItems;
|
||||
}
|
||||
@@ -1638,6 +1670,7 @@
|
||||
@@ -1638,6 +1672,7 @@
|
||||
_invalidateCachedTabs() {
|
||||
this.#allTabs = null;
|
||||
this._invalidateCachedVisibleTabs();
|
||||
@@ -243,7 +245,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
}
|
||||
|
||||
_invalidateCachedVisibleTabs() {
|
||||
@@ -1652,8 +1685,8 @@
|
||||
@@ -1652,8 +1687,8 @@
|
||||
#isContainerVerticalPinnedExpanded(tab) {
|
||||
return (
|
||||
this.verticalMode &&
|
||||
@@ -254,7 +256,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1668,7 +1701,7 @@
|
||||
@@ -1668,7 +1703,7 @@
|
||||
|
||||
if (node == null) {
|
||||
// We have a container for non-tab elements at the end of the scrollbox.
|
||||
@@ -263,7 +265,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
}
|
||||
|
||||
node.before(tab);
|
||||
@@ -1763,7 +1796,7 @@
|
||||
@@ -1763,7 +1798,7 @@
|
||||
// There are separate "new tab" buttons for horizontal tabs toolbar, vertical tabs and
|
||||
// for when the tab strip is overflowed (which is shared by vertical and horizontal tabs);
|
||||
// Attach the long click popup to all of them.
|
||||
@@ -272,7 +274,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
const newTab2 = this.newTabButton;
|
||||
const newTabVertical = document.getElementById(
|
||||
"vertical-tabs-newtab-button"
|
||||
@@ -1846,7 +1879,7 @@
|
||||
@@ -1846,7 +1881,7 @@
|
||||
let rect = ele => {
|
||||
return window.windowUtils.getBoundsWithoutFlushing(ele);
|
||||
};
|
||||
@@ -281,7 +283,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
if (tab && rect(tab).width <= this._tabClipWidth) {
|
||||
this.setAttribute("closebuttons", "activetab");
|
||||
} else {
|
||||
@@ -1858,10 +1891,12 @@
|
||||
@@ -1858,10 +1893,12 @@
|
||||
|
||||
_handleTabSelect(aInstant) {
|
||||
let selectedTab = this.selectedItem;
|
||||
@@ -294,7 +296,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
selectedTab._notselectedsinceload = false;
|
||||
}
|
||||
|
||||
@@ -1873,7 +1908,7 @@
|
||||
@@ -1873,7 +1910,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -303,7 +305,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
if (!tabs.length) {
|
||||
return;
|
||||
}
|
||||
@@ -1909,7 +1944,7 @@
|
||||
@@ -1909,7 +1946,7 @@
|
||||
if (isEndTab && !this._hasTabTempMaxWidth) {
|
||||
return;
|
||||
}
|
||||
@@ -312,7 +314,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
// Force tabs to stay the same width, unless we're closing the last tab,
|
||||
// which case we need to let them expand just enough so that the overall
|
||||
// tabbar width is the same.
|
||||
@@ -1924,7 +1959,7 @@
|
||||
@@ -1924,7 +1961,7 @@
|
||||
let tabsToReset = [];
|
||||
for (let i = numPinned; i < tabs.length; i++) {
|
||||
let tab = tabs[i];
|
||||
@@ -321,7 +323,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
if (!isEndTab) {
|
||||
// keep tabs the same width
|
||||
tab.style.transition = "none";
|
||||
@@ -1990,16 +2025,15 @@
|
||||
@@ -1990,16 +2027,15 @@
|
||||
// Move pinned tabs to another container when the tabstrip is toggled to vertical
|
||||
// and when session restore code calls _positionPinnedTabs; update styling whenever
|
||||
// the number of pinned tabs changes.
|
||||
@@ -344,7 +346,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2007,9 +2041,7 @@
|
||||
@@ -2007,9 +2043,7 @@
|
||||
}
|
||||
|
||||
_resetVerticalPinnedTabs() {
|
||||
@@ -355,7 +357,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
|
||||
if (!verticalTabsContainer.children.length) {
|
||||
return;
|
||||
@@ -2022,8 +2054,8 @@
|
||||
@@ -2022,8 +2056,8 @@
|
||||
}
|
||||
|
||||
_positionPinnedTabs() {
|
||||
@@ -366,7 +368,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
let absPositionHorizontalTabs =
|
||||
this.overflowing && tabs.length > numPinned && numPinned > 0;
|
||||
|
||||
@@ -2032,7 +2064,7 @@
|
||||
@@ -2032,7 +2066,7 @@
|
||||
|
||||
if (this.verticalMode) {
|
||||
this._updateVerticalPinnedTabs();
|
||||
@@ -375,7 +377,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
let layoutData = this._pinnedTabsLayoutCache;
|
||||
let uiDensity = document.documentElement.getAttribute("uidensity");
|
||||
if (!layoutData || layoutData.uiDensity != uiDensity) {
|
||||
@@ -2104,7 +2136,7 @@
|
||||
@@ -2104,7 +2138,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -384,7 +386,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
|
||||
let directionX = screenX > dragData.animLastScreenX;
|
||||
let directionY = screenY > dragData.animLastScreenY;
|
||||
@@ -2112,7 +2144,7 @@
|
||||
@@ -2112,7 +2146,7 @@
|
||||
dragData.animLastScreenX = screenX;
|
||||
|
||||
let { width: tabWidth, height: tabHeight } =
|
||||
@@ -393,7 +395,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
let shiftSizeX = tabWidth * movingTabs.length;
|
||||
let shiftSizeY = tabHeight;
|
||||
dragData.tabWidth = tabWidth;
|
||||
@@ -2296,11 +2328,15 @@
|
||||
@@ -2296,11 +2330,15 @@
|
||||
this.#clearDragOverCreateGroupTimer();
|
||||
|
||||
let isPinned = draggedTab.pinned;
|
||||
@@ -413,7 +415,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
|
||||
if (this.#rtlMode) {
|
||||
tabs.reverse();
|
||||
@@ -2314,7 +2350,7 @@
|
||||
@@ -2314,7 +2352,7 @@
|
||||
let size = this.verticalMode ? "height" : "width";
|
||||
let translateAxis = this.verticalMode ? "translateY" : "translateX";
|
||||
let scrollDirection = this.verticalMode ? "scrollTop" : "scrollLeft";
|
||||
@@ -422,7 +424,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
let translateX = event.screenX - dragData.screenX;
|
||||
let translateY = event.screenY - dragData.screenY;
|
||||
|
||||
@@ -2328,6 +2364,12 @@
|
||||
@@ -2328,6 +2366,12 @@
|
||||
let lastTab = tabs.at(-1);
|
||||
let lastMovingTab = movingTabs.at(-1);
|
||||
let firstMovingTab = movingTabs[0];
|
||||
@@ -435,7 +437,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
let endEdge = ele => ele[screenAxis] + bounds(ele)[size];
|
||||
let lastMovingTabScreen = endEdge(lastMovingTab);
|
||||
let firstMovingTabScreen = firstMovingTab[screenAxis];
|
||||
@@ -2348,7 +2390,11 @@
|
||||
@@ -2348,7 +2392,11 @@
|
||||
translate = Math.min(Math.max(translate, firstBound), lastBound);
|
||||
|
||||
for (let tab of movingTabs) {
|
||||
@@ -448,7 +450,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
}
|
||||
|
||||
dragData.translatePos = translate;
|
||||
@@ -2485,6 +2531,9 @@
|
||||
@@ -2485,6 +2533,9 @@
|
||||
break;
|
||||
}
|
||||
let element = tabs[mid];
|
||||
@@ -458,7 +460,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
let elementForSize = isTabGroupLabel(element)
|
||||
? element.parentElement
|
||||
: element;
|
||||
@@ -2507,6 +2556,10 @@
|
||||
@@ -2507,6 +2558,10 @@
|
||||
if (!dropElement) {
|
||||
dropElement = this.ariaFocusableItems[oldDropElementIndex];
|
||||
}
|
||||
@@ -469,7 +471,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
let newDropElementIndex = dropElement
|
||||
? dropElement.elementIndex
|
||||
: oldDropElementIndex;
|
||||
@@ -2515,7 +2568,7 @@
|
||||
@@ -2515,7 +2570,7 @@
|
||||
let shouldCreateGroupOnDrop;
|
||||
let dropBefore;
|
||||
if (dropElement) {
|
||||
@@ -478,7 +480,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
? dropElement.parentElement
|
||||
: dropElement;
|
||||
|
||||
@@ -2566,12 +2619,12 @@
|
||||
@@ -2566,12 +2621,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -493,7 +495,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
dropElement != draggedTab &&
|
||||
isTab(dropElement) &&
|
||||
!dropElement?.group &&
|
||||
@@ -2639,7 +2692,7 @@
|
||||
@@ -2639,7 +2694,7 @@
|
||||
// Shift background tabs to leave a gap where the dragged tab
|
||||
// would currently be dropped.
|
||||
for (let item of tabs) {
|
||||
@@ -502,7 +504,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2648,6 +2701,9 @@
|
||||
@@ -2648,6 +2703,9 @@
|
||||
if (isTabGroupLabel(item)) {
|
||||
// Shift the `.tab-group-label-container` to shift the label element.
|
||||
item = item.parentElement;
|
||||
@@ -512,7 +514,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
}
|
||||
item.style.transform = transform;
|
||||
}
|
||||
@@ -2697,8 +2753,9 @@
|
||||
@@ -2697,8 +2755,9 @@
|
||||
);
|
||||
}
|
||||
|
||||
@@ -524,7 +526,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2711,6 +2768,12 @@
|
||||
@@ -2711,6 +2770,12 @@
|
||||
item = item.parentElement;
|
||||
}
|
||||
item.style.transform = "";
|
||||
@@ -537,7 +539,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
item.removeAttribute("dragover-createGroup");
|
||||
}
|
||||
this.removeAttribute("movingtab-createGroup");
|
||||
@@ -2754,7 +2817,7 @@
|
||||
@@ -2754,7 +2819,7 @@
|
||||
let postTransitionCleanup = () => {
|
||||
movingTab._moveTogetherSelectedTabsData.animate = false;
|
||||
};
|
||||
@@ -546,7 +548,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0d3919b288afefb05e3ec54ddfa90f00
|
||||
postTransitionCleanup();
|
||||
} else {
|
||||
let onTransitionEnd = transitionendEvent => {
|
||||
@@ -2924,7 +2987,7 @@
|
||||
@@ -2924,7 +2989,7 @@
|
||||
}
|
||||
|
||||
_notifyBackgroundTab(aTab) {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/components/urlbar/UrlbarInput.sys.mjs b/browser/components/urlbar/UrlbarInput.sys.mjs
|
||||
index 6de4c2ac873b1424abee118a143ac377f26beb80..3b41d52c8e00860ce9913a334f15f70e1db08a7c 100644
|
||||
index 6de4c2ac873b1424abee118a143ac377f26beb80..23b4d238d767000b9f0de74cfc13c862f1d17b8d 100644
|
||||
--- a/browser/components/urlbar/UrlbarInput.sys.mjs
|
||||
+++ b/browser/components/urlbar/UrlbarInput.sys.mjs
|
||||
@@ -67,6 +67,13 @@ XPCOMUtils.defineLazyPreferenceGetter(
|
||||
@@ -52,18 +52,7 @@ index 6de4c2ac873b1424abee118a143ac377f26beb80..3b41d52c8e00860ce9913a334f15f70e
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -937,6 +955,10 @@ export class UrlbarInput {
|
||||
// Nullify search mode before setURI so it won't try to restore it.
|
||||
this.searchMode = null;
|
||||
this.setURI(null, true, false, true);
|
||||
+ if (this.hasAttribute("zen-floating-urlbar")) {
|
||||
+ this.window.gBrowser.selectedBrowser.focus();
|
||||
+ return;
|
||||
+ }
|
||||
if (this.value && this.focused) {
|
||||
this.select();
|
||||
}
|
||||
@@ -1092,7 +1114,11 @@ export class UrlbarInput {
|
||||
@@ -1092,7 +1110,11 @@ export class UrlbarInput {
|
||||
}
|
||||
|
||||
if (!this.#providesSearchMode(result)) {
|
||||
@@ -76,7 +65,7 @@ index 6de4c2ac873b1424abee118a143ac377f26beb80..3b41d52c8e00860ce9913a334f15f70e
|
||||
}
|
||||
|
||||
this.controller.recordSelectedResult(event, result);
|
||||
@@ -2124,6 +2150,10 @@ export class UrlbarInput {
|
||||
@@ -2124,6 +2146,10 @@ export class UrlbarInput {
|
||||
await this.#updateLayoutBreakoutDimensions();
|
||||
}
|
||||
|
||||
@@ -87,7 +76,7 @@ index 6de4c2ac873b1424abee118a143ac377f26beb80..3b41d52c8e00860ce9913a334f15f70e
|
||||
startLayoutExtend() {
|
||||
if (!this.#allowBreakout || this.hasAttribute("breakout-extend")) {
|
||||
// Do not expand if the Urlbar does not support being expanded or it is
|
||||
@@ -2146,6 +2176,11 @@ export class UrlbarInput {
|
||||
@@ -2146,6 +2172,11 @@ export class UrlbarInput {
|
||||
|
||||
this.setAttribute("breakout-extend", "true");
|
||||
|
||||
@@ -99,19 +88,27 @@ index 6de4c2ac873b1424abee118a143ac377f26beb80..3b41d52c8e00860ce9913a334f15f70e
|
||||
// Enable the animation only after the first extend call to ensure it
|
||||
// doesn't run when opening a new window.
|
||||
if (!this.hasAttribute("breakout-extend-animate")) {
|
||||
@@ -2165,6 +2200,11 @@ export class UrlbarInput {
|
||||
@@ -2165,6 +2196,19 @@ export class UrlbarInput {
|
||||
return;
|
||||
}
|
||||
|
||||
+ if (this._zenHandleUrlbarClose) {
|
||||
+ this._zenHandleUrlbarClose();
|
||||
+ }
|
||||
+
|
||||
+ // Arc like URLbar: Blur the input on exit
|
||||
+ this.document.getElementById("navigator-toolbox").setAttribute("supress-primary-adjustment", !this.document.getElementById("navigator-toolbox").hasAttribute("zen-has-hover"));
|
||||
+ this.window.gBrowser.selectedBrowser.focus();
|
||||
+ this.window.setTimeout(() => {
|
||||
+ this.document.getElementById("navigator-toolbox").removeAttribute("supress-primary-adjustment");
|
||||
+ }, 100);
|
||||
+
|
||||
+ this.removeAttribute("zen-floating-urlbar");
|
||||
+
|
||||
this.removeAttribute("breakout-extend");
|
||||
this.#updateTextboxPosition();
|
||||
}
|
||||
@@ -2997,7 +3037,7 @@ export class UrlbarInput {
|
||||
@@ -2997,7 +3041,7 @@ export class UrlbarInput {
|
||||
*/
|
||||
_trimValue(val) {
|
||||
let trimmedValue = lazy.UrlbarPrefs.get("trimURLs")
|
||||
@@ -120,16 +117,18 @@ index 6de4c2ac873b1424abee118a143ac377f26beb80..3b41d52c8e00860ce9913a334f15f70e
|
||||
: val;
|
||||
// Only trim value if the directionality doesn't change to RTL and we're not
|
||||
// showing a strikeout https protocol.
|
||||
@@ -3359,7 +3399,7 @@ export class UrlbarInput {
|
||||
} else {
|
||||
where = lazy.BrowserUtils.whereToOpenLink(event, false, false);
|
||||
@@ -3367,6 +3411,10 @@ export class UrlbarInput {
|
||||
}
|
||||
reuseEmpty = true;
|
||||
}
|
||||
- if (lazy.UrlbarPrefs.get("openintab")) {
|
||||
+ if (lazy.UrlbarPrefs.get("openintab") || this.hasAttribute("zen-newtab")) {
|
||||
if (where == "current") {
|
||||
where = "tab";
|
||||
} else if (where == "tab") {
|
||||
@@ -3374,6 +3414,9 @@ export class UrlbarInput {
|
||||
+ if (this.hasAttribute("zen-newtab")) {
|
||||
+ where = "tab";
|
||||
+ reuseEmpty = true;
|
||||
+ }
|
||||
if (
|
||||
where == "tab" &&
|
||||
reuseEmpty &&
|
||||
@@ -3374,6 +3422,9 @@ export class UrlbarInput {
|
||||
) {
|
||||
where = "current";
|
||||
}
|
||||
@@ -139,7 +138,24 @@ index 6de4c2ac873b1424abee118a143ac377f26beb80..3b41d52c8e00860ce9913a334f15f70e
|
||||
return where;
|
||||
}
|
||||
|
||||
@@ -4048,6 +4091,11 @@ export class UrlbarInput {
|
||||
@@ -3625,7 +3676,7 @@ export class UrlbarInput {
|
||||
pasteAndGo.setAttribute("anonid", "paste-and-go");
|
||||
pasteAndGo.addEventListener("command", () => {
|
||||
this._suppressStartQuery = true;
|
||||
-
|
||||
+ this.view.close();
|
||||
this.select();
|
||||
this.window.goDoCommand("cmd_paste");
|
||||
this.setResultForCurrentValue(null);
|
||||
@@ -3638,7 +3689,6 @@ export class UrlbarInput {
|
||||
contextMenu.addEventListener("popupshowing", () => {
|
||||
// Close the results pane when the input field contextual menu is open,
|
||||
// because paste and go doesn't want a result selection.
|
||||
- this.view.close();
|
||||
|
||||
let controller =
|
||||
this.document.commandDispatcher.getControllerForCommand("cmd_paste");
|
||||
@@ -4048,6 +4098,11 @@ export class UrlbarInput {
|
||||
}
|
||||
|
||||
_on_click(event) {
|
||||
@@ -151,7 +167,7 @@ index 6de4c2ac873b1424abee118a143ac377f26beb80..3b41d52c8e00860ce9913a334f15f70e
|
||||
if (
|
||||
event.target == this.inputField ||
|
||||
event.target == this._inputContainer ||
|
||||
@@ -4119,7 +4167,7 @@ export class UrlbarInput {
|
||||
@@ -4119,7 +4174,7 @@ export class UrlbarInput {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,7 +176,7 @@ index 6de4c2ac873b1424abee118a143ac377f26beb80..3b41d52c8e00860ce9913a334f15f70e
|
||||
this.view.autoOpen({ event });
|
||||
} else {
|
||||
if (this._untrimOnFocusAfterKeydown) {
|
||||
@@ -4159,9 +4207,12 @@ export class UrlbarInput {
|
||||
@@ -4159,9 +4214,12 @@ export class UrlbarInput {
|
||||
}
|
||||
|
||||
_on_mousedown(event) {
|
||||
@@ -174,7 +190,7 @@ index 6de4c2ac873b1424abee118a143ac377f26beb80..3b41d52c8e00860ce9913a334f15f70e
|
||||
|
||||
if (
|
||||
event.target != this.inputField &&
|
||||
@@ -4171,8 +4222,8 @@ export class UrlbarInput {
|
||||
@@ -4171,8 +4229,8 @@ export class UrlbarInput {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@@ -1181,6 +1181,24 @@ menupopup > menuitem:is([type='checkbox']) .menu-iconic-left {
|
||||
list-style-image: url('close.svg') !important;
|
||||
}
|
||||
|
||||
#zen-media-mute-mic-button {
|
||||
list-style-image: url('microphone-fill.svg') !important;
|
||||
}
|
||||
|
||||
#zen-media-controls-toolbar[mic-muted] #zen-media-mute-mic-button {
|
||||
list-style-image: url('microphone-blocked-fill.svg') !important;
|
||||
fill: rgb(224, 41, 29);
|
||||
}
|
||||
|
||||
#zen-media-mute-camera-button {
|
||||
list-style-image: url('video-fill.svg') !important;
|
||||
}
|
||||
|
||||
#zen-media-controls-toolbar[camera-muted] #zen-media-mute-camera-button {
|
||||
list-style-image: url('video-blocked-fill.svg') !important;
|
||||
fill: rgb(224, 41, 29);
|
||||
}
|
||||
|
||||
#zen-media-pip-button {
|
||||
list-style-image: url('chrome://global/skin/media/picture-in-picture-open.svg') !important;
|
||||
}
|
||||
|
@@ -75,7 +75,9 @@
|
||||
skin/classic/browser/zen-icons/media-unmute.svg (../shared/zen-icons/lin/media-unmute.svg)
|
||||
skin/classic/browser/zen-icons/menu-bar.svg (../shared/zen-icons/lin/menu-bar.svg)
|
||||
skin/classic/browser/zen-icons/menu.svg (../shared/zen-icons/lin/menu.svg)
|
||||
skin/classic/browser/zen-icons/microphone-blocked-fill.svg (../shared/zen-icons/lin/microphone-blocked-fill.svg)
|
||||
skin/classic/browser/zen-icons/microphone-blocked.svg (../shared/zen-icons/lin/microphone-blocked.svg)
|
||||
skin/classic/browser/zen-icons/microphone-fill.svg (../shared/zen-icons/lin/microphone-fill.svg)
|
||||
skin/classic/browser/zen-icons/microphone.svg (../shared/zen-icons/lin/microphone.svg)
|
||||
skin/classic/browser/zen-icons/midi.svg (../shared/zen-icons/lin/midi.svg)
|
||||
skin/classic/browser/zen-icons/move-tab.svg (../shared/zen-icons/lin/move-tab.svg)
|
||||
@@ -125,8 +127,10 @@
|
||||
skin/classic/browser/zen-icons/tracking-protection.svg (../shared/zen-icons/lin/tracking-protection.svg)
|
||||
skin/classic/browser/zen-icons/translations.svg (../shared/zen-icons/lin/translations.svg)
|
||||
skin/classic/browser/zen-icons/unpin.svg (../shared/zen-icons/lin/unpin.svg)
|
||||
skin/classic/browser/zen-icons/video-blocked-fill.svg (../shared/zen-icons/lin/video-blocked-fill.svg)
|
||||
skin/classic/browser/zen-icons/video-open.svg (../shared/zen-icons/lin/video-open.svg)
|
||||
skin/classic/browser/zen-icons/video-save.svg (../shared/zen-icons/lin/video-save.svg)
|
||||
skin/classic/browser/zen-icons/video-fill.svg (../shared/zen-icons/lin/video-fill.svg)
|
||||
skin/classic/browser/zen-icons/window.svg (../shared/zen-icons/lin/window.svg)
|
||||
skin/classic/browser/zen-icons/xr-blocked.svg (../shared/zen-icons/lin/xr-blocked.svg)
|
||||
skin/classic/browser/zen-icons/xr.svg (../shared/zen-icons/lin/xr.svg)
|
||||
@@ -209,7 +213,9 @@
|
||||
skin/classic/browser/zen-icons/media-unmute.svg (../shared/zen-icons/lin/media-unmute.svg)
|
||||
skin/classic/browser/zen-icons/menu-bar.svg (../shared/zen-icons/lin/menu-bar.svg)
|
||||
skin/classic/browser/zen-icons/menu.svg (../shared/zen-icons/lin/menu.svg)
|
||||
skin/classic/browser/zen-icons/microphone-blocked-fill.svg (../shared/zen-icons/lin/microphone-blocked-fill.svg)
|
||||
skin/classic/browser/zen-icons/microphone-blocked.svg (../shared/zen-icons/lin/microphone-blocked.svg)
|
||||
skin/classic/browser/zen-icons/microphone-fill.svg (../shared/zen-icons/lin/microphone-fill.svg)
|
||||
skin/classic/browser/zen-icons/microphone.svg (../shared/zen-icons/lin/microphone.svg)
|
||||
skin/classic/browser/zen-icons/midi.svg (../shared/zen-icons/lin/midi.svg)
|
||||
skin/classic/browser/zen-icons/move-tab.svg (../shared/zen-icons/lin/move-tab.svg)
|
||||
@@ -259,8 +265,10 @@
|
||||
skin/classic/browser/zen-icons/tracking-protection.svg (../shared/zen-icons/lin/tracking-protection.svg)
|
||||
skin/classic/browser/zen-icons/translations.svg (../shared/zen-icons/lin/translations.svg)
|
||||
skin/classic/browser/zen-icons/unpin.svg (../shared/zen-icons/lin/unpin.svg)
|
||||
skin/classic/browser/zen-icons/video-blocked-fill.svg (../shared/zen-icons/lin/video-blocked-fill.svg)
|
||||
skin/classic/browser/zen-icons/video-open.svg (../shared/zen-icons/lin/video-open.svg)
|
||||
skin/classic/browser/zen-icons/video-save.svg (../shared/zen-icons/lin/video-save.svg)
|
||||
skin/classic/browser/zen-icons/video-fill.svg (../shared/zen-icons/lin/video-fill.svg)
|
||||
skin/classic/browser/zen-icons/window.svg (../shared/zen-icons/lin/window.svg)
|
||||
skin/classic/browser/zen-icons/xr-blocked.svg (../shared/zen-icons/lin/xr-blocked.svg)
|
||||
skin/classic/browser/zen-icons/xr.svg (../shared/zen-icons/lin/xr.svg)
|
||||
@@ -343,7 +351,9 @@
|
||||
skin/classic/browser/zen-icons/media-unmute.svg (../shared/zen-icons/lin/media-unmute.svg)
|
||||
skin/classic/browser/zen-icons/menu-bar.svg (../shared/zen-icons/lin/menu-bar.svg)
|
||||
skin/classic/browser/zen-icons/menu.svg (../shared/zen-icons/lin/menu.svg)
|
||||
skin/classic/browser/zen-icons/microphone-blocked-fill.svg (../shared/zen-icons/lin/microphone-blocked-fill.svg)
|
||||
skin/classic/browser/zen-icons/microphone-blocked.svg (../shared/zen-icons/lin/microphone-blocked.svg)
|
||||
skin/classic/browser/zen-icons/microphone-fill.svg (../shared/zen-icons/lin/microphone-fill.svg)
|
||||
skin/classic/browser/zen-icons/microphone.svg (../shared/zen-icons/lin/microphone.svg)
|
||||
skin/classic/browser/zen-icons/midi.svg (../shared/zen-icons/lin/midi.svg)
|
||||
skin/classic/browser/zen-icons/move-tab.svg (../shared/zen-icons/lin/move-tab.svg)
|
||||
@@ -393,8 +403,10 @@
|
||||
skin/classic/browser/zen-icons/tracking-protection.svg (../shared/zen-icons/lin/tracking-protection.svg)
|
||||
skin/classic/browser/zen-icons/translations.svg (../shared/zen-icons/lin/translations.svg)
|
||||
skin/classic/browser/zen-icons/unpin.svg (../shared/zen-icons/lin/unpin.svg)
|
||||
skin/classic/browser/zen-icons/video-blocked-fill.svg (../shared/zen-icons/lin/video-blocked-fill.svg)
|
||||
skin/classic/browser/zen-icons/video-open.svg (../shared/zen-icons/lin/video-open.svg)
|
||||
skin/classic/browser/zen-icons/video-save.svg (../shared/zen-icons/lin/video-save.svg)
|
||||
skin/classic/browser/zen-icons/video-fill.svg (../shared/zen-icons/lin/video-fill.svg)
|
||||
skin/classic/browser/zen-icons/window.svg (../shared/zen-icons/lin/window.svg)
|
||||
skin/classic/browser/zen-icons/xr-blocked.svg (../shared/zen-icons/lin/xr-blocked.svg)
|
||||
skin/classic/browser/zen-icons/xr.svg (../shared/zen-icons/lin/xr.svg)
|
||||
|
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="18px" height="18px" viewBox="0 0 18 18"><path d="M6.721,11.279l6.279-6.279c0-2.206-1.794-4-4-4s-4,1.794-4,4v3c0,1.358,.683,2.556,1.721,3.279Z" fill="context-fill" stroke-opacity="context-fill-opacity"></path><path d="M9.202,11.979c2.042-.104,3.673-1.736,3.777-3.777l-3.777,3.777Z" fill="context-fill" stroke-opacity="context-fill-opacity"></path><path d="M4.583,13.417l1.066-1.066c-1.304-1.006-2.149-2.58-2.149-4.351,0-.414-.336-.75-.75-.75s-.75,.336-.75,.75c0,2.185,1.01,4.133,2.583,5.417Z" fill="context-fill" stroke-opacity="context-fill-opacity" data-color="color-2"></path><path d="M15.25,7.25c-.414,0-.75,.336-.75,.75,0,3.033-2.467,5.5-5.5,5.5-.408,0-.804-.048-1.186-.132l-1.203,1.203c.521,.19,1.069,.327,1.639,.388v1.292c0,.414,.336,.75,.75,.75s.75-.336,.75-.75v-1.292c3.508-.376,6.25-3.352,6.25-6.958,0-.414-.336-.75-.75-.75Z" fill="context-fill" stroke-opacity="context-fill-opacity" data-color="color-2"></path><path d="M2,16.75c-.192,0-.384-.073-.53-.22-.293-.293-.293-.768,0-1.061L15.47,1.47c.293-.293,.768-.293,1.061,0s.293,.768,0,1.061L2.53,16.53c-.146,.146-.338,.22-.53,.22Z" fill="context-fill" stroke-opacity="context-fill-opacity" data-color="color-2"></path></svg>
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="18px" height="18px" viewBox="0 0 18 18"><path d="M9,12c2.206,0,4-1.794,4-4v-3c0-2.206-1.794-4-4-4s-4,1.794-4,4v3c0,2.206,1.794,4,4,4Z" fill="context-fill" stroke-opacity="context-fill-opacity"></path><path d="M15.25,7.25c-.414,0-.75,.336-.75,.75,0,3.033-2.467,5.5-5.5,5.5s-5.5-2.467-5.5-5.5c0-.414-.336-.75-.75-.75s-.75,.336-.75,.75c0,3.606,2.742,6.583,6.25,6.958v1.292c0,.414,.336,.75,.75,.75s.75-.336,.75-.75v-1.292c3.508-.376,6.25-3.352,6.25-6.958,0-.414-.336-.75-.75-.75Z" fill="context-fill" stroke-opacity="context-fill-opacity" data-color="color-2"></path></svg>
|
After Width: | Height: | Size: 675 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="18px" height="18px" viewBox="0 0 18 18"><path d="M6.182,15h3.568c1.517,0,2.75-1.233,2.75-2.75v-3.568l-6.318,6.318Z" fill="context-fill" stroke-opacity="context-fill-opacity"></path><path d="M3.089,14.911L12.477,5.523c-.118-1.409-1.288-2.523-2.727-2.523H3.75c-1.517,0-2.75,1.233-2.75,2.75v6.5c0,1.288,.893,2.363,2.089,2.661Zm1.911-8.911c.552,0,1,.448,1,1s-.448,1-1,1-1-.448-1-1,.448-1,1-1Z" fill="context-fill" stroke-opacity="context-fill-opacity"></path><path d="M17.386,5.019c-.368-.217-.805-.227-1.183-.04l-2.203,2.203v4.637l2.147,1.181c.19,.105,.397,.157,.604,.157,.219,0,.438-.059,.635-.175,.385-.228,.614-.63,.614-1.077V6.096c0-.447-.229-.849-.614-1.077Z" fill="context-fill" stroke-opacity="context-fill-opacity"></path><path d="M2,16.75c-.192,0-.384-.073-.53-.22-.293-.293-.293-.768,0-1.061L15.47,1.47c.293-.293,.768-.293,1.061,0s.293,.768,0,1.061L2.53,16.53c-.146,.146-.338,.22-.53,.22Z" fill="context-fill" stroke-opacity="context-fill-opacity" data-color="color-2"></path></svg>
|
After Width: | Height: | Size: 1.1 KiB |
1
src/browser/themes/shared/zen-icons/lin/video-fill.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="18px" height="18px" viewBox="0 0 18 18"><path d="M17.386,5.019c-.385-.227-.848-.234-1.238-.019l-2.148,1.181v5.637l2.147,1.181c.19,.105,.397,.157,.604,.157,.219,0,.438-.059,.635-.175,.385-.228,.614-.63,.614-1.077V6.096c0-.447-.229-.849-.614-1.077Z" fill="context-fill" stroke-opacity="context-fill-opacity" data-color="color-2"></path><path d="M9.75,3H3.75c-1.517,0-2.75,1.233-2.75,2.75v6.5c0,1.517,1.233,2.75,2.75,2.75h6c1.517,0,2.75-1.233,2.75-2.75V5.75c0-1.517-1.233-2.75-2.75-2.75Zm-4.75,5c-.552,0-1-.448-1-1s.448-1,1-1,1,.448,1,1-.448,1-1,1Z" fill="context-fill" stroke-opacity="context-fill-opacity"></path></svg>
|
After Width: | Height: | Size: 724 B |
@@ -1,8 +1,8 @@
|
||||
diff --git a/browser/themes/windows/browser.css b/browser/themes/windows/browser.css
|
||||
index 9af78803f0005a2b89e1c73f52153ed4d9e3154a..b63dc3d050144f048ac6a326acd57cc85fa8a3a7 100644
|
||||
index 9af78803f0005a2b89e1c73f52153ed4d9e3154a..f5b21a09347f5890da3eef0efa38a66195c8e418 100644
|
||||
--- a/browser/themes/windows/browser.css
|
||||
+++ b/browser/themes/windows/browser.css
|
||||
@@ -40,14 +40,13 @@
|
||||
@@ -40,13 +40,12 @@
|
||||
* override these on the tabs toolbar because the accent color is
|
||||
* arbitrary, so the hardcoded colors from browser-custom-colors might
|
||||
* not provide sufficient contrast. */
|
||||
@@ -12,9 +12,8 @@ index 9af78803f0005a2b89e1c73f52153ed4d9e3154a..b63dc3d050144f048ac6a326acd57cc8
|
||||
}
|
||||
}
|
||||
|
||||
&[sizemode="normal"] #navigator-toolbox {
|
||||
- border-top: .5px solid ActiveBorder;
|
||||
+ /* border-top: .5px solid ActiveBorder; Zen: Remove annoying top border, dont remove */
|
||||
- &[sizemode="normal"] #navigator-toolbox {
|
||||
+ &[sizemode="normal"] #browser {
|
||||
border-top: .5px solid ActiveBorder;
|
||||
&:-moz-window-inactive {
|
||||
border-top-color: InactiveBorder;
|
||||
}
|
||||
|
16
src/makensis-mk.patch
Normal file
@@ -0,0 +1,16 @@
|
||||
diff --git a/toolkit/mozapps/installer/windows/nsis/makensis.mk b/toolkit/mozapps/installer/windows/nsis/makensis.mk
|
||||
index b4425034fb198fd5303af513d81a3db6b4d14e36..8c44945b4448eb1c69a73894b3e13fc8d2ef3ade 100644
|
||||
--- a/toolkit/mozapps/installer/windows/nsis/makensis.mk
|
||||
+++ b/toolkit/mozapps/installer/windows/nsis/makensis.mk
|
||||
@@ -64,6 +64,11 @@ endif
|
||||
ifdef ZIP_IN
|
||||
installer:: $(CONFIG_DIR)/setup.exe $(ZIP_IN)
|
||||
@echo 'Packaging $(WIN32_INSTALLER_OUT).'
|
||||
+ifneq ("$(ZEN_SETUP_EXE_PATH)","")
|
||||
+ @echo 'setup-zen.exe exists, moving it to setup.exe ($(ZEN_SETUP_EXE_PATH))'
|
||||
+ rm $(CONFIG_DIR)/setup.exe
|
||||
+ cp $(ZEN_SETUP_EXE_PATH) $(CONFIG_DIR)/setup.exe
|
||||
+endif
|
||||
$(NSINSTALL) -D '$(ABS_DIST)/$(PKG_INST_PATH)'
|
||||
$(PYTHON3) $(MOZILLA_DIR)/mach repackage installer \
|
||||
-o '$(ABS_DIST)/$(PKG_INST_PATH)$(PKG_INST_BASENAME).exe' \
|
@@ -1,24 +1,8 @@
|
||||
diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml
|
||||
index 85974462e5ce2b7dbf85bd5c79f09b3db5c25915..f914f5c0f29be4149be15265bb6571ae92fb23cc 100644
|
||||
index 2f0bb8a6e21bec5c89a4a25413bf8d1308210f52..450d8265c128861f3ad5973ec0417b9463ebffd0 100644
|
||||
--- a/modules/libpref/init/StaticPrefList.yaml
|
||||
+++ b/modules/libpref/init/StaticPrefList.yaml
|
||||
@@ -18462,13 +18462,13 @@
|
||||
# Whether we use the mica backdrop. Off by default for now.
|
||||
- name: widget.windows.mica
|
||||
type: bool
|
||||
- value: false
|
||||
+ value: true
|
||||
mirror: always
|
||||
|
||||
# Whether we use the mica backdrop for popups. Off by default for now.
|
||||
- name: widget.windows.mica.popups
|
||||
type: RelaxedAtomicBool
|
||||
- value: false
|
||||
+ value: true
|
||||
mirror: always
|
||||
|
||||
# Whether we expand the client area into the taskbar hidden edge on maximized
|
||||
@@ -18594,6 +18594,7 @@
|
||||
@@ -18598,6 +18598,7 @@
|
||||
mirror: always
|
||||
#endif
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
diff --git a/toolkit/components/pictureinpicture/PictureInPicture.sys.mjs b/toolkit/components/pictureinpicture/PictureInPicture.sys.mjs
|
||||
index 5da0404b2672ba8cce7bcf808bf2373474776654..1405c53a927a64ecda8255d78d9aa5ddf8806685 100644
|
||||
index 5da0404b2672ba8cce7bcf808bf2373474776654..3b93217b38f25f54d7ef44d151e314bc1c5e5ce3 100644
|
||||
--- a/toolkit/components/pictureinpicture/PictureInPicture.sys.mjs
|
||||
+++ b/toolkit/components/pictureinpicture/PictureInPicture.sys.mjs
|
||||
@@ -494,7 +494,7 @@ export var PictureInPicture = {
|
||||
@@ -11,11 +11,3 @@ index 5da0404b2672ba8cce7bcf808bf2373474776654..1405c53a927a64ecda8255d78d9aa5dd
|
||||
await this.closeSinglePipWindow({ reason: "Unpip", actorRef: pipActor });
|
||||
},
|
||||
|
||||
@@ -623,6 +623,7 @@ export var PictureInPicture = {
|
||||
pipToggle.hidden = true;
|
||||
}
|
||||
|
||||
+ win.gZenMediaController.updatePipEligibility(browser, !pipToggle.hidden);
|
||||
let browserHasPip = !!this.browserWeakMap.get(browser);
|
||||
if (browserHasPip) {
|
||||
this.setUrlbarPipIconActive(browser.ownerGlobal);
|
||||
|
19
src/toolkit/modules/ShortcutUtils-sys-mjs.patch
Normal file
@@ -0,0 +1,19 @@
|
||||
diff --git a/toolkit/modules/ShortcutUtils.sys.mjs b/toolkit/modules/ShortcutUtils.sys.mjs
|
||||
index 360a7dbeeae3899af01945e35d5fe3aa0cb3c562..895d39fe5887ffae9cdbce9576df8b00d4cc8442 100644
|
||||
--- a/toolkit/modules/ShortcutUtils.sys.mjs
|
||||
+++ b/toolkit/modules/ShortcutUtils.sys.mjs
|
||||
@@ -382,12 +382,12 @@ export var ShortcutUtils = {
|
||||
return ShortcutUtils.MOVE_TAB_FORWARD;
|
||||
}
|
||||
break;
|
||||
- case event.DOM_VK_LEFT:
|
||||
+ case event.DOM_VK_UP: // For macOS, make sure if this patch needs to be updated
|
||||
if (accelMetaKey && event.altKey && !event.shiftKey && !event.ctrlKey) {
|
||||
return ShortcutUtils.PREVIOUS_TAB;
|
||||
}
|
||||
break;
|
||||
- case event.DOM_VK_RIGHT:
|
||||
+ case event.DOM_VK_DOWN: // For macOS, make sure if this patch needs to be updated
|
||||
if (accelMetaKey && event.altKey && !event.shiftKey && !event.ctrlKey) {
|
||||
return ShortcutUtils.NEXT_TAB;
|
||||
}
|
@@ -35,7 +35,7 @@ index 849b62c9976a7bc5fee35e074e54c8f556ed9c38..a9742c7ff30d417a18f41f9c12025919
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +95,7 @@ static NSVisualEffectBlendingMode VisualEffectBlendingModeForVibrancyType(
|
||||
@@ -78,6 +95,7 @@ - (NSView*)hitTest:(NSPoint)aPoint {
|
||||
|
||||
- (void)prefChanged {
|
||||
self.blendingMode = VisualEffectBlendingModeForVibrancyType(mType);
|
||||
|
@@ -30,7 +30,6 @@
|
||||
|
||||
this._initSidebarScrolling();
|
||||
|
||||
gZenCompactModeManager.init();
|
||||
ZenWorkspaces.init();
|
||||
gZenVerticalTabsManager.init();
|
||||
gZenUIManager.init();
|
||||
@@ -41,7 +40,39 @@
|
||||
} catch (e) {
|
||||
console.error('ZenThemeModifier: Error initializing browser layout', e);
|
||||
}
|
||||
ZenWorkspaces.promiseInitialized.then(() => {
|
||||
if (gBrowserInit.delayedStartupFinished) {
|
||||
this.delayedStartupFinished();
|
||||
} else {
|
||||
Services.obs.addObserver(this, 'browser-delayed-startup-finished');
|
||||
}
|
||||
},
|
||||
|
||||
observe(aSubject, aTopic) {
|
||||
// This nsIObserver method allows us to defer initialization until after
|
||||
// this window has finished painting and starting up.
|
||||
if (aTopic == 'browser-delayed-startup-finished' && aSubject == window) {
|
||||
Services.obs.removeObserver(this, 'browser-delayed-startup-finished');
|
||||
this.delayedStartupFinished();
|
||||
}
|
||||
},
|
||||
|
||||
delayedStartupFinished() {
|
||||
ZenWorkspaces.promiseInitialized.then(async () => {
|
||||
await delayedStartupPromise;
|
||||
await SessionStore.promiseAllWindowsRestored;
|
||||
setTimeout(() => {
|
||||
gZenCompactModeManager.init();
|
||||
setTimeout(() => {
|
||||
// A bit of a hack to make sure the tabs toolbar is updated.
|
||||
// Just in case we didn't get the right size.
|
||||
gZenUIManager.updateTabsToolbar();
|
||||
|
||||
// Fix for https://github.com/zen-browser/desktop/issues/7605, specially in compact mode
|
||||
if (gURLBar.hasAttribute('breakout-extend')) {
|
||||
gURLBar.focus();
|
||||
}
|
||||
}, 100);
|
||||
}, 0);
|
||||
this.closeWatermark();
|
||||
});
|
||||
},
|
@@ -88,9 +88,11 @@ var gZenUIManager = {
|
||||
this.tabsWrapper.scrollTop = this._scrollbarState;
|
||||
},
|
||||
|
||||
onTabClose(event) {
|
||||
this.updateTabsToolbar();
|
||||
this.restoreScrollbarState();
|
||||
onTabClose(event = undefined) {
|
||||
if (!event?.target?._closedInMultiselection) {
|
||||
this.updateTabsToolbar();
|
||||
this.restoreScrollbarState();
|
||||
}
|
||||
},
|
||||
|
||||
openAndChangeToTab(url, options) {
|
||||
@@ -464,6 +466,19 @@ var gZenVerticalTabsManager = {
|
||||
}
|
||||
},
|
||||
|
||||
recalculateURLBarHeight() {
|
||||
document.getElementById('urlbar').removeAttribute('--urlbar-height');
|
||||
if (!this._hasSetSingleToolbar) {
|
||||
document.getElementById('urlbar').style.setProperty('--urlbar-height', '32px');
|
||||
} else {
|
||||
try {
|
||||
gURLBar.zenUpdateLayoutBreakout();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_updateEvent({ forCustomizableMode = false, dontRebuildAreas = false } = {}) {
|
||||
if (this._isUpdating) {
|
||||
return;
|
||||
@@ -544,7 +559,7 @@ var gZenVerticalTabsManager = {
|
||||
);
|
||||
elements = Array.from(elements).reverse();
|
||||
// Add separator if it doesn't exist
|
||||
if (!buttonsTarget.contains(this._topButtonsSeparatorElement)) {
|
||||
if (!this._hasSetSingleToolbar) {
|
||||
buttonsTarget.append(this._topButtonsSeparatorElement);
|
||||
}
|
||||
for (const button of elements) {
|
||||
@@ -642,21 +657,14 @@ var gZenVerticalTabsManager = {
|
||||
}
|
||||
|
||||
gZenCompactModeManager.updateCompactModeContext(isSingleToolbar);
|
||||
document.getElementById('urlbar').removeAttribute('--urlbar-height');
|
||||
if (!isSingleToolbar) {
|
||||
document.getElementById('urlbar').style.setProperty('--urlbar-height', '32px');
|
||||
} else {
|
||||
try {
|
||||
gURLBar.zenUpdateLayoutBreakout();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
this.recalculateURLBarHeight();
|
||||
|
||||
// Always move the splitter next to the sidebar
|
||||
this.navigatorToolbox.after(document.getElementById('zen-sidebar-splitter'));
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
gZenCompactModeManager.getAndApplySidebarWidth();
|
||||
if (!isCompactMode) {
|
||||
gZenCompactModeManager.getAndApplySidebarWidth();
|
||||
}
|
||||
gZenUIManager.updateTabsToolbar();
|
||||
} catch (e) {
|
||||
console.error(e);
|
@@ -4,7 +4,8 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
:root:not([inDOMFullscreen='true']):not([chromehidden~='location']):not([chromehidden~='toolbar']) {
|
||||
& #tabbrowser-tabbox #tabbrowser-tabpanels .browserSidebarContainer {
|
||||
& #tabbrowser-tabbox #tabbrowser-tabpanels .browserSidebarContainer,
|
||||
#tabbrowser-tabpanels[dragging-split='true'] {
|
||||
width: -moz-available;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
@@ -21,9 +22,11 @@
|
||||
|
||||
@media -moz-pref('zen.view.experimental-rounded-view') {
|
||||
#tabbrowser-tabpanels {
|
||||
mix-blend-mode: multiply;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
isolation: isolate;
|
||||
:root:not([zen-no-padding='true']) & {
|
||||
mix-blend-mode: multiply;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
isolation: isolate;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -43,6 +43,8 @@ panel[type='arrow'] {
|
||||
--panel-border-color: transparent !important;
|
||||
--panel-shadow-margin: 0px !important;
|
||||
|
||||
transition-duration: 0s !important;
|
||||
|
||||
&::part(content) {
|
||||
animation: none !important;
|
||||
}
|
@@ -4,40 +4,6 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#zen-profile-button {
|
||||
& stack {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
& .toolbarbutton-badge {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
& stack {
|
||||
width: calc(2 * var(--toolbarbutton-inner-padding) + 16px) !important;
|
||||
height: calc(2 * var(--toolbarbutton-inner-padding) + 16px) !important;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
& > image {
|
||||
width: 0;
|
||||
}
|
||||
}
|
||||
|
||||
& #zen-profile-button-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
list-style-image: var(--avatar-image-url);
|
||||
border-radius: 50%;
|
||||
pointer-events: none;
|
||||
list-style-image: var(--avatar-image-url);
|
||||
-moz-context-properties: fill;
|
||||
fill: currentColor;
|
||||
border: 1px solid var(--zen-colors-border);
|
||||
}
|
||||
}
|
||||
|
||||
/* Bookmarks sidebar */
|
||||
#zen-tabbox-wrapper {
|
||||
& #sidebar-splitter {
|
||||
@@ -49,7 +15,12 @@
|
||||
border-radius: var(--zen-native-inner-radius);
|
||||
box-shadow: var(--zen-big-shadow);
|
||||
overflow: hidden;
|
||||
|
||||
&[positionend=''] {
|
||||
order: 6;
|
||||
& ~ #sidebar-splitter {
|
||||
order: 5;
|
||||
}
|
||||
}
|
||||
:root:not([zen-right-side='true']) &[positionend='true'] {
|
||||
margin-right: var(--zen-element-separation);
|
||||
}
|
@@ -118,6 +118,7 @@
|
||||
--toolbar-field-focus-background-color: var(--urlbar-box-bgcolor) !important;
|
||||
--zen-input-border-color: light-dark(rgb(204, 204, 204), rgb(66, 65, 77));
|
||||
--urlbar-box-hover-bgcolor: var(--toolbarbutton-hover-background) !important;
|
||||
--input-bgcolor: light-dark(rgba(255, 255, 255, 0.2), rgba(0, 0, 0, 0.2)) !important;
|
||||
|
||||
/* XUL */
|
||||
--zen-main-browser-background: light-dark(rgb(235, 235, 235), #1b1b1b);
|
||||
@@ -167,6 +168,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
@media (-moz-platform: linux) and -moz-pref('zen.widget.linux.transparency') {
|
||||
background: transparent;
|
||||
--zen-themed-toolbar-bg-transparent: transparent;
|
||||
}
|
||||
|
||||
--toolbar-field-background-color: var(--zen-colors-input-bg) !important;
|
||||
--arrowpanel-background: var(--zen-dialog-background) !important;
|
||||
|
@@ -9,5 +9,5 @@
|
||||
}
|
||||
|
||||
:root[inDOMFullscreen='true'] #zen-appcontent-navbar-container {
|
||||
display: none;
|
||||
visibility: collapse;
|
||||
}
|
@@ -365,10 +365,6 @@ button.popup-notification-dropmarker {
|
||||
}
|
||||
|
||||
:root:not([zen-single-toolbar='true']) {
|
||||
& #nav-bar {
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
|
||||
&[zen-right-side='true']:not([zen-window-buttons-reversed='true']) #nav-bar {
|
||||
margin-inline-start: var(--zen-element-separation);
|
||||
}
|
@@ -1,3 +1,7 @@
|
||||
// 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/.
|
||||
|
||||
document.addEventListener(
|
||||
'MozBeforeInitialXULLayout',
|
||||
() => {
|
@@ -11,6 +11,7 @@
|
||||
*/
|
||||
|
||||
const kZenThemePrefsList = ['zen.theme.accent-color', 'zen.theme.border-radius', 'zen.theme.content-element-separation'];
|
||||
const kZenMaxElementSeparation = 12;
|
||||
|
||||
/**
|
||||
* ZenThemeModifier controls the application of theme data to the browser,
|
||||
@@ -68,7 +69,7 @@ var ZenThemeModifier = {
|
||||
},
|
||||
|
||||
updateElementSeparation() {
|
||||
const separation = Services.prefs.getIntPref('zen.theme.content-element-separation');
|
||||
let separation = this.elementSeparation;
|
||||
document.documentElement.style.setProperty('--zen-element-separation', separation + 'px');
|
||||
if (separation == 0) {
|
||||
document.documentElement.setAttribute('zen-no-padding', true);
|
||||
@@ -77,6 +78,10 @@ var ZenThemeModifier = {
|
||||
}
|
||||
},
|
||||
|
||||
get elementSeparation() {
|
||||
return Math.min(Services.prefs.getIntPref('zen.theme.content-element-separation'), kZenMaxElementSeparation);
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the accent color.
|
||||
*/
|
@@ -28,15 +28,23 @@ var gZenCompactModeManager = {
|
||||
_evenListeners: [],
|
||||
_removeHoverFrames: {},
|
||||
|
||||
preInit() {
|
||||
// Remove it before initializing so we can properly calculate the width
|
||||
// of the sidebar at startup and avoid overflowing items not being hidden
|
||||
const isCompactMode = lazyCompactMode.mainAppWrapper.getAttribute('zen-compact-mode') === 'true';
|
||||
lazyCompactMode.mainAppWrapper.removeAttribute('zen-compact-mode');
|
||||
this._wasInCompactMode = isCompactMode;
|
||||
|
||||
this.addMouseActions();
|
||||
this.addContextMenu();
|
||||
},
|
||||
|
||||
init() {
|
||||
Services.prefs.addObserver('zen.tabs.vertical.right-side', this._updateSidebarIsOnRight.bind(this));
|
||||
|
||||
gZenUIManager.addPopupTrackingAttribute(this.sidebar);
|
||||
gZenUIManager.addPopupTrackingAttribute(document.getElementById('zen-appcontent-navbar-container'));
|
||||
|
||||
this.addMouseActions();
|
||||
this.addContextMenu();
|
||||
|
||||
// Clear hover states when window state changes (minimize, maximize, etc.)
|
||||
window.addEventListener('sizemodechange', () => this._clearAllHoverStates());
|
||||
|
||||
@@ -47,26 +55,19 @@ var gZenCompactModeManager = {
|
||||
buttons.removeAttribute('zen-has-hover');
|
||||
});
|
||||
}
|
||||
this.preference = this._wasInCompactMode;
|
||||
},
|
||||
|
||||
get preference() {
|
||||
if (!document.documentElement.hasAttribute('zen-compact-mode')) {
|
||||
window.addEventListener(
|
||||
'MozAfterPaint',
|
||||
() => {
|
||||
document.documentElement.setAttribute(
|
||||
'zen-compact-mode',
|
||||
lazyCompactMode.mainAppWrapper.getAttribute('zen-compact-mode')
|
||||
);
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
}
|
||||
return lazyCompactMode.mainAppWrapper.getAttribute('zen-compact-mode') === 'true';
|
||||
},
|
||||
|
||||
set preference(value) {
|
||||
if (this.preference === value || document.documentElement.hasAttribute('zen-compact-animating')) {
|
||||
if (typeof this._wasInCompactMode !== 'undefined') {
|
||||
// We wont do anything with it anyway, so we remove it
|
||||
delete this._wasInCompactMode;
|
||||
}
|
||||
// We dont want the user to be able to spam the button
|
||||
return value;
|
||||
}
|
||||
@@ -94,6 +95,11 @@ var gZenCompactModeManager = {
|
||||
},
|
||||
|
||||
flashSidebarIfNecessary(aInstant = false) {
|
||||
// This function is called after exiting DOM fullscreen mode,
|
||||
// so we do a bit of a hack to re-calculate the URL height
|
||||
if (aInstant) {
|
||||
gZenVerticalTabsManager.recalculateURLBarHeight();
|
||||
}
|
||||
if (!aInstant && this.preference && lazyCompactMode.COMPACT_MODE_FLASH_ENABLED && !gZenGlanceManager._animating) {
|
||||
this.flashSidebar();
|
||||
}
|
||||
@@ -156,11 +162,16 @@ var gZenCompactModeManager = {
|
||||
await this.animateCompactMode();
|
||||
this._evenListeners.forEach((callback) => callback());
|
||||
}
|
||||
gZenUIManager.updateTabsToolbar();
|
||||
},
|
||||
|
||||
// NOTE: Dont actually use event, it's just so we make sure
|
||||
// the caller is from the ResizeObserver
|
||||
getAndApplySidebarWidth(event = undefined) {
|
||||
if (this._ignoreNextResize) {
|
||||
this._ignoreNextResize = false;
|
||||
return;
|
||||
}
|
||||
let sidebarWidth = this.sidebar.getBoundingClientRect().width;
|
||||
if (sidebarWidth > 1) {
|
||||
gZenUIManager.restoreScrollbarState();
|
||||
@@ -184,18 +195,18 @@ var gZenCompactModeManager = {
|
||||
const isCompactMode = this.preference;
|
||||
const canHideSidebar =
|
||||
Services.prefs.getBoolPref('zen.view.compact.hide-tabbar') || gZenVerticalTabsManager._hasSetSingleToolbar;
|
||||
const canAnimate =
|
||||
let canAnimate =
|
||||
lazyCompactMode.COMPACT_MODE_CAN_ANIMATE_SIDEBAR &&
|
||||
!this.sidebar.hasAttribute('zen-user-show') &&
|
||||
!this.sidebar.hasAttribute('zen-has-empty-tab') &&
|
||||
!this.sidebar.hasAttribute('zen-has-hover');
|
||||
if (typeof this._wasInCompactMode !== 'undefined') {
|
||||
canAnimate = false;
|
||||
delete this._wasInCompactMode;
|
||||
}
|
||||
// Do this so we can get the correct width ONCE compact mode styled have been applied
|
||||
const titlebar = this.sidebar.querySelector('#titlebar');
|
||||
if (canAnimate) {
|
||||
this.sidebar.setAttribute('animate', 'true');
|
||||
titlebar.setAttribute('has-animated-padding', 'true');
|
||||
} else {
|
||||
titlebar.removeAttribute('has-animated-padding');
|
||||
}
|
||||
this.sidebar.style.removeProperty('margin-right');
|
||||
this.sidebar.style.removeProperty('margin-left');
|
||||
@@ -205,11 +216,22 @@ var gZenCompactModeManager = {
|
||||
if (!canAnimate) {
|
||||
this.sidebar.removeAttribute('animate');
|
||||
document.documentElement.removeAttribute('zen-compact-animating');
|
||||
|
||||
this.getAndApplySidebarWidth({});
|
||||
this._ignoreNextResize = true;
|
||||
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
if (canHideSidebar && isCompactMode) {
|
||||
sidebarWidth -= 0.5 * splitterWidth;
|
||||
const elementSeparation = ZenThemeModifier.elementSeparation;
|
||||
if (document.documentElement.hasAttribute('zen-sidebar-expanded')) {
|
||||
sidebarWidth -= 0.5 * splitterWidth;
|
||||
if (elementSeparation < splitterWidth) {
|
||||
// Subtract from the splitter width to end up with the correct element separation
|
||||
sidebarWidth += 1.5 * splitterWidth - elementSeparation;
|
||||
}
|
||||
}
|
||||
gZenUIManager.motion
|
||||
.animate(
|
||||
this.sidebar,
|
||||
@@ -227,25 +249,17 @@ var gZenCompactModeManager = {
|
||||
.then(() => {
|
||||
this.sidebar.style.transition = 'none';
|
||||
this.sidebar.style.opacity = 0;
|
||||
this.getAndApplySidebarWidth();
|
||||
setTimeout(() => {
|
||||
this.sidebar.removeAttribute('animate');
|
||||
document.documentElement.removeAttribute('zen-compact-animating');
|
||||
|
||||
this.getAndApplySidebarWidth({});
|
||||
this._ignoreNextResize = true;
|
||||
|
||||
this.sidebar.style.removeProperty('margin-right');
|
||||
this.sidebar.style.removeProperty('margin-left');
|
||||
if (this.sidebarIsOnRight) {
|
||||
this.sidebar.style.right = `-100%`;
|
||||
} else {
|
||||
this.sidebar.style.left = `-100%`;
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
this.sidebar.style.left = '';
|
||||
this.sidebar.style.right = '';
|
||||
this.sidebar.style.removeProperty('opacity');
|
||||
this.sidebar.style.removeProperty('transform');
|
||||
this.sidebar.style.removeProperty('transition');
|
||||
}, 200);
|
||||
this.sidebar.style.removeProperty('opacity');
|
||||
this.sidebar.style.removeProperty('transition');
|
||||
|
||||
resolve();
|
||||
}, 0);
|
||||
@@ -416,13 +430,6 @@ var gZenCompactModeManager = {
|
||||
}
|
||||
}
|
||||
|
||||
// When moving the cursor between the url bar and bookmarks, or in-between bookmarks in the bookmark bar, the
|
||||
// mouseLeave event is triggered without a relatedTarget.
|
||||
// TODO: Experiment with this for some time, see if people still have issues with the hover state
|
||||
//if (event.relatedTarget == null) {
|
||||
// return;
|
||||
//}
|
||||
|
||||
// If it's a child element but not the target, ignore the event
|
||||
if (target.contains(event.explicitOriginalTarget) && event.explicitOriginalTarget !== target) {
|
||||
return;
|
||||
@@ -500,3 +507,11 @@ var gZenCompactModeManager = {
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
document.addEventListener(
|
||||
'MozBeforeInitialXULLayout',
|
||||
() => {
|
||||
gZenCompactModeManager.preInit();
|
||||
},
|
||||
{ once: true }
|
||||
);
|
@@ -6,7 +6,7 @@
|
||||
/* All overrides for compact mode go here */
|
||||
|
||||
:root[zen-compact-mode='true']:not([customizing]):not([inDOMFullscreen='true']) {
|
||||
%include zen-tabs/vertical-tabs-topbuttons-fix.css
|
||||
%include ../tabs/zen-tabs/vertical-tabs-topbuttons-fix.css
|
||||
@media -moz-pref('zen.view.compact.hide-tabbar') or -moz-pref('zen.view.use-single-toolbar') {
|
||||
&:not([zen-compact-animating]) {
|
||||
& #zen-sidebar-splitter {
|
||||
@@ -114,15 +114,10 @@
|
||||
background: var(--zen-dialog-background);
|
||||
outline: 1px solid var(--zen-colors-border-contrast);
|
||||
outline-offset: -1px;
|
||||
/* times 4 because we have the inner padding and the outter padding to consider */
|
||||
:root[zen-sidebar-expanded='true'] & {
|
||||
&[has-animated-padding='true'] {
|
||||
width: calc(var(--zen-sidebar-width) + var(--zen-toolbox-padding));
|
||||
}
|
||||
min-width: var(--zen-toolbox-min-width);
|
||||
|
||||
&:not([has-animated-padding='true']) {
|
||||
width: calc(var(--zen-sidebar-width) - var(--zen-toolbox-padding));
|
||||
}
|
||||
:root[zen-sidebar-expanded='true'] & {
|
||||
width: calc(var(--zen-sidebar-width) + var(--zen-toolbox-padding));
|
||||
}
|
||||
|
||||
:root[zen-single-toolbar='true'] {
|
||||
@@ -142,10 +137,6 @@
|
||||
& #urlbar[open][zen-floating-urlbar='true'] {
|
||||
transition: left 0.05s ease;
|
||||
visibility: visible;
|
||||
|
||||
#navigator-toolbox:has(&) {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&::before {
|
||||
@@ -281,9 +272,9 @@
|
||||
transition:
|
||||
left 0.25s var(--zen-compact-mode-func),
|
||||
right 0.25s var(--zen-compact-mode-func);
|
||||
opacity: 1;
|
||||
|
||||
&:not([supress-primary-adjustment='true']) {
|
||||
opacity: 1;
|
||||
left: calc(var(--zen-element-separation) / -2);
|
||||
:root[zen-right-side='true'] & {
|
||||
right: calc(var(--zen-element-separation) / -2);
|
||||
@@ -305,7 +296,6 @@
|
||||
--zen-toolbox-top-align: var(--zen-element-separation);
|
||||
}
|
||||
|
||||
& #sidebar-box,
|
||||
& #titlebar,
|
||||
& #zen-appcontent-wrapper,
|
||||
& #zen-sidebar-web-panel-wrapper:has(#zen-sidebar-web-panel:not([pinned='true'])) {
|
||||
@@ -344,7 +334,7 @@
|
||||
}
|
||||
|
||||
& #urlbar {
|
||||
opacity: 0;
|
||||
opacity: 0 !important;
|
||||
}
|
||||
|
||||
@media -moz-pref('zen.view.compact.color-toolbar') {
|
||||
@@ -356,6 +346,7 @@
|
||||
}
|
||||
|
||||
& #zen-appcontent-navbar-container[zen-has-hover],
|
||||
& #zen-appcontent-navbar-container:hover,
|
||||
& #zen-appcontent-navbar-container:focus-within,
|
||||
& #zen-appcontent-navbar-container[zen-user-show],
|
||||
& #zen-appcontent-navbar-container[has-popup-menu],
|
||||
@@ -382,7 +373,7 @@
|
||||
}
|
||||
|
||||
& #urlbar {
|
||||
opacity: 1;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
& #urlbar[breakout-extend='true']:not([zen-floating-urlbar='true']) {
|
||||
@@ -393,3 +384,21 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Fix for https://github.com/zen-browser/desktop/issues/7615 */
|
||||
:root[zen-compact-mode='true']:not([customizing])[inDOMFullscreen='true'] {
|
||||
@media -moz-pref('zen.view.compact.hide-tabbar') or -moz-pref('zen.view.use-single-toolbar') {
|
||||
&:not([zen-compact-animating]) {
|
||||
#navigator-toolbox {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@media -moz-pref('zen.view.compact.hide-toolbar') {
|
||||
&:not([zen-single-toolbar='true']) {
|
||||
& #zen-appcontent-navbar-container {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,3 +1,9 @@
|
||||
/*
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
tab-group[split-view-group] {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
@@ -464,8 +464,12 @@
|
||||
this.#currentGlanceID = tab.getAttribute('glance-id');
|
||||
if (gBrowser.selectedTab === this.#currentParentTab && this.#currentBrowser) {
|
||||
const curTab = this.#currentTab;
|
||||
const prevTab = event.detail.previousTab;
|
||||
setTimeout(() => {
|
||||
gBrowser.selectedTab = curTab;
|
||||
if (prevTab?.linkedBrowser) {
|
||||
prevTab.linkedBrowser.closest('.browserSidebarContainer').classList.remove('deck-selected');
|
||||
}
|
||||
}, 0);
|
||||
} else if (gBrowser.selectedTab === this.#currentTab) {
|
||||
setTimeout(this.onLocationChangeOpenGlance.bind(this), 0);
|
||||
@@ -661,7 +665,7 @@
|
||||
},
|
||||
},
|
||||
allFrames: true,
|
||||
matches: ['https://*/*'],
|
||||
matches: ['*://*/*'],
|
||||
});
|
||||
}
|
||||
}
|
10
src/zen/glance/moz.build
Normal file
@@ -0,0 +1,10 @@
|
||||
#
|
||||
# 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/.
|
||||
|
||||
|
||||
FINAL_TARGET_FILES.actors += [
|
||||
"actors/ZenGlanceChild.sys.mjs",
|
||||
"actors/ZenGlanceParent.sys.mjs",
|
||||
]
|
@@ -4,11 +4,6 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
.browserSidebarContainer:has([zen-glance-selected]),
|
||||
.browserSidebarContainer.zen-glance-overlay {
|
||||
visibility: inherit;
|
||||
}
|
||||
|
||||
#zen-glance-sidebar-container {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
@@ -88,18 +83,32 @@
|
||||
}
|
||||
}
|
||||
|
||||
:root[zen-no-padding='true'] .browserSidebarContainer.zen-glance-background {
|
||||
--zen-native-inner-radius: 6px;
|
||||
--zen-element-separation: 6px;
|
||||
}
|
||||
|
||||
.browserSidebarContainer.zen-glance-background,
|
||||
.browserSidebarContainer.zen-glance-overlay .browserContainer {
|
||||
border-radius: var(--zen-native-inner-radius);
|
||||
box-shadow: var(--zen-big-shadow);
|
||||
}
|
||||
|
||||
.browserSidebarContainer.zen-glance-overlay {
|
||||
box-shadow: none !important;
|
||||
visibility: inherit;
|
||||
|
||||
:root[zen-no-padding='true'] & {
|
||||
--zen-native-inner-radius: 0px;
|
||||
}
|
||||
|
||||
& .browserContainer {
|
||||
background: var(--zen-dialog-background);
|
||||
position: fixed;
|
||||
border-radius: var(--zen-native-inner-radius);
|
||||
opacity: 0;
|
||||
top: 0;
|
||||
left: 0;
|
||||
flex: unset !important;
|
||||
box-shadow: var(--zen-big-shadow);
|
||||
|
||||
&[has-finished-animation='true'] {
|
||||
position: relative !important;
|
Before Width: | Height: | Size: 803 B After Width: | Height: | Size: 803 B |
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 67 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 513 KiB After Width: | Height: | Size: 513 KiB |
Before Width: | Height: | Size: 522 KiB After Width: | Height: | Size: 522 KiB |
Before Width: | Height: | Size: 525 KiB After Width: | Height: | Size: 525 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
657
src/zen/media/ZenMediaController.mjs
Normal file
@@ -0,0 +1,657 @@
|
||||
{
|
||||
const lazy = {};
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
lazy,
|
||||
'RESPECT_PIP_DISABLED',
|
||||
'media.videocontrols.picture-in-picture.respect-disablePictureInPicture',
|
||||
true
|
||||
);
|
||||
|
||||
class ZenMediaController {
|
||||
_currentMediaController = null;
|
||||
_currentBrowser = null;
|
||||
_mediaUpdateInterval = null;
|
||||
|
||||
mediaTitle = null;
|
||||
mediaArtist = null;
|
||||
mediaControlBar = null;
|
||||
mediaProgressBar = null;
|
||||
mediaCurrentTime = null;
|
||||
mediaDuration = null;
|
||||
mediaFocusButton = null;
|
||||
mediaProgressBarContainer = null;
|
||||
|
||||
supportedKeys = ['playpause', 'previoustrack', 'nexttrack'];
|
||||
mediaControllersMap = new Map();
|
||||
|
||||
_tabTimeout = null;
|
||||
_controllerSwitchTimeout = null;
|
||||
|
||||
#isSeeking = false;
|
||||
|
||||
init() {
|
||||
if (!Services.prefs.getBoolPref('zen.mediacontrols.enabled', true)) return;
|
||||
|
||||
this.mediaTitle = document.querySelector('#zen-media-title');
|
||||
this.mediaArtist = document.querySelector('#zen-media-artist');
|
||||
this.mediaControlBar = document.querySelector('#zen-media-controls-toolbar');
|
||||
this.mediaProgressBar = document.querySelector('#zen-media-progress-bar');
|
||||
this.mediaCurrentTime = document.querySelector('#zen-media-current-time');
|
||||
this.mediaDuration = document.querySelector('#zen-media-duration');
|
||||
this.mediaFocusButton = document.querySelector('#zen-media-focus-button');
|
||||
this.mediaProgressBarContainer = document.querySelector('#zen-media-progress-hbox');
|
||||
|
||||
this.onPositionstateChange = this._onPositionstateChange.bind(this);
|
||||
this.onPlaybackstateChange = this._onPlaybackstateChange.bind(this);
|
||||
this.onSupportedKeysChange = this._onSupportedKeysChange.bind(this);
|
||||
this.onMetadataChange = this._onMetadataChange.bind(this);
|
||||
this.onDeactivated = this._onDeactivated.bind(this);
|
||||
this.onPipModeChange = this._onPictureInPictureModeChange.bind(this);
|
||||
|
||||
this.#initEventListeners();
|
||||
}
|
||||
|
||||
#initEventListeners() {
|
||||
this.mediaControlBar.addEventListener('mousedown', (event) => {
|
||||
if (event.target.closest(':is(toolbarbutton,#zen-media-progress-hbox)')) return;
|
||||
else this.onMediaFocus();
|
||||
});
|
||||
|
||||
this.mediaControlBar.addEventListener('command', (event) => {
|
||||
const button = event.target.closest('toolbarbutton');
|
||||
if (!button) return;
|
||||
switch (button.id) {
|
||||
case 'zen-media-pip-button':
|
||||
this.onMediaPip();
|
||||
break;
|
||||
case 'zen-media-close-button':
|
||||
this.onControllerClose();
|
||||
break;
|
||||
case 'zen-media-focus-button':
|
||||
this.onMediaFocus();
|
||||
break;
|
||||
case 'zen-media-mute-button':
|
||||
this.onMediaMute();
|
||||
break;
|
||||
case 'zen-media-previoustrack-button':
|
||||
this.onMediaPlayPrev();
|
||||
break;
|
||||
case 'zen-media-nexttrack-button':
|
||||
this.onMediaPlayNext();
|
||||
break;
|
||||
case 'zen-media-playpause-button':
|
||||
this.onMediaToggle();
|
||||
break;
|
||||
case 'zen-media-mute-mic-button':
|
||||
this.onMicrophoneMuteToggle();
|
||||
break;
|
||||
case 'zen-media-mute-camera-button':
|
||||
this.onCameraMuteToggle();
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
this.mediaProgressBar.addEventListener('input', this.onMediaSeekDrag.bind(this));
|
||||
this.mediaProgressBar.addEventListener('change', this.onMediaSeekComplete.bind(this));
|
||||
|
||||
window.addEventListener('TabSelect', (event) => {
|
||||
if (this.isSharing) return;
|
||||
|
||||
const linkedBrowser = event.target.linkedBrowser;
|
||||
this.switchController();
|
||||
|
||||
if (this._currentBrowser) {
|
||||
if (linkedBrowser.browserId === this._currentBrowser.browserId) {
|
||||
if (this._tabTimeout) {
|
||||
clearTimeout(this._tabTimeout);
|
||||
this._tabTimeout = null;
|
||||
}
|
||||
|
||||
this.hideMediaControls();
|
||||
} else {
|
||||
this._tabTimeout = setTimeout(() => {
|
||||
if (!this.mediaControlBar.hasAttribute('pip')) this.showMediaControls();
|
||||
else this._tabTimeout = null;
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const onTabDiscardedOrClosed = this.onTabDiscardedOrClosed.bind(this);
|
||||
|
||||
window.addEventListener('TabClose', onTabDiscardedOrClosed);
|
||||
window.addEventListener('TabBrowserDiscarded', onTabDiscardedOrClosed);
|
||||
|
||||
window.addEventListener('DOMAudioPlaybackStarted', (event) => {
|
||||
setTimeout(() => {
|
||||
if (
|
||||
this._currentMediaController?.isPlaying &&
|
||||
this.mediaControlBar.hasAttribute('hidden') &&
|
||||
!this.mediaControlBar.hasAttribute('pip')
|
||||
) {
|
||||
const { selectedBrowser } = gBrowser;
|
||||
if (selectedBrowser.browserId !== this._currentBrowser.browserId) {
|
||||
this.showMediaControls();
|
||||
}
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
this.activateMediaControls(event.target.browsingContext.mediaController, event.target);
|
||||
});
|
||||
|
||||
window.addEventListener('DOMAudioPlaybackStopped', () => this.updateMuteState());
|
||||
}
|
||||
|
||||
onTabDiscardedOrClosed(event) {
|
||||
const { linkedBrowser } = event.target;
|
||||
const isCurrentBrowser = linkedBrowser?.browserId === this._currentBrowser?.browserId;
|
||||
|
||||
if (isCurrentBrowser) {
|
||||
this.isSharing = false;
|
||||
this.hideMediaControls();
|
||||
}
|
||||
|
||||
if (linkedBrowser?.browsingContext?.mediaController) {
|
||||
this.deinitMediaController(linkedBrowser.browsingContext.mediaController, true, isCurrentBrowser, true);
|
||||
}
|
||||
}
|
||||
|
||||
async deinitMediaController(mediaController, shouldForget = true, shouldOverride = true, shouldHide = true) {
|
||||
if (shouldForget && mediaController) {
|
||||
mediaController.removeEventListener('pictureinpicturemodechange', this.onPipModeChange);
|
||||
mediaController.removeEventListener('positionstatechange', this.onPositionstateChange);
|
||||
mediaController.removeEventListener('playbackstatechange', this.onPlaybackstateChange);
|
||||
mediaController.removeEventListener('supportedkeyschange', this.onSupportedKeysChange);
|
||||
mediaController.removeEventListener('metadatachange', this.onMetadataChange);
|
||||
mediaController.removeEventListener('deactivated', this.onDeactivated);
|
||||
|
||||
this.mediaControllersMap.delete(mediaController.id);
|
||||
}
|
||||
|
||||
if (shouldOverride) {
|
||||
this._currentMediaController = null;
|
||||
this._currentBrowser = null;
|
||||
|
||||
if (this._mediaUpdateInterval) {
|
||||
clearInterval(this._mediaUpdateInterval);
|
||||
this._mediaUpdateInterval = null;
|
||||
}
|
||||
|
||||
if (shouldHide) await this.hideMediaControls();
|
||||
this.mediaControlBar.removeAttribute('muted');
|
||||
this.mediaControlBar.classList.remove('playing');
|
||||
}
|
||||
}
|
||||
|
||||
get isSharing() {
|
||||
return this.mediaControlBar.hasAttribute('media-sharing');
|
||||
}
|
||||
|
||||
set isSharing(value) {
|
||||
if (this._currentBrowser?.browsingContext && !value) {
|
||||
const webRTC = this._currentBrowser.browsingContext.currentWindowGlobal.getActor('WebRTC');
|
||||
webRTC.sendAsyncMessage('webrtc:UnmuteMicrophone');
|
||||
webRTC.sendAsyncMessage('webrtc:UnmuteCamera');
|
||||
}
|
||||
|
||||
if (!value) {
|
||||
this.mediaControlBar.removeAttribute('mic-muted');
|
||||
this.mediaControlBar.removeAttribute('camera-muted');
|
||||
} else {
|
||||
this.mediaControlBar.setAttribute('media-position-hidden', '');
|
||||
this.mediaControlBar.setAttribute('media-sharing', '');
|
||||
}
|
||||
}
|
||||
|
||||
hideMediaControls() {
|
||||
if (this.mediaControlBar.hasAttribute('hidden')) return;
|
||||
|
||||
return gZenUIManager.motion
|
||||
.animate(
|
||||
this.mediaControlBar,
|
||||
{
|
||||
opacity: [1, 0],
|
||||
y: [0, 10],
|
||||
},
|
||||
{
|
||||
duration: 0.1,
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
this.mediaControlBar.setAttribute('hidden', 'true');
|
||||
this.mediaControlBar.removeAttribute('media-sharing');
|
||||
gZenUIManager.updateTabsToolbar();
|
||||
gZenUIManager.restoreScrollbarState();
|
||||
});
|
||||
}
|
||||
|
||||
showMediaControls() {
|
||||
if (!this.mediaControlBar.hasAttribute('hidden')) return;
|
||||
|
||||
if (!this.isSharing) {
|
||||
if (!this._currentMediaController) return;
|
||||
if (this._currentMediaController.isBeingUsedInPIPModeOrFullscreen) return this.hideMediaControls();
|
||||
|
||||
this.updatePipButton();
|
||||
}
|
||||
|
||||
const mediaInfoElements = [this.mediaTitle, this.mediaArtist];
|
||||
for (const element of mediaInfoElements) {
|
||||
element.removeAttribute('overflow'); // So we can properly recalculate the overflow
|
||||
}
|
||||
|
||||
this.mediaControlBar.removeAttribute('hidden');
|
||||
window.requestAnimationFrame(() => {
|
||||
this.mediaControlBar.style.height =
|
||||
this.mediaControlBar.querySelector('toolbaritem').getBoundingClientRect().height + 'px';
|
||||
this.mediaControlBar.style.opacity = 0;
|
||||
gZenUIManager.updateTabsToolbar();
|
||||
gZenUIManager.restoreScrollbarState();
|
||||
gZenUIManager.motion.animate(
|
||||
this.mediaControlBar,
|
||||
{
|
||||
opacity: [0, 1],
|
||||
y: [10, 0],
|
||||
},
|
||||
{}
|
||||
);
|
||||
this.addLabelOverflows(mediaInfoElements);
|
||||
});
|
||||
}
|
||||
|
||||
addLabelOverflows(elements) {
|
||||
for (const element of elements) {
|
||||
const parent = element.parentElement;
|
||||
if (element.scrollWidth > parent.clientWidth) {
|
||||
element.setAttribute('overflow', '');
|
||||
} else {
|
||||
element.removeAttribute('overflow');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setupMediaController(mediaController, browser) {
|
||||
this._currentMediaController = mediaController;
|
||||
this._currentBrowser = browser;
|
||||
|
||||
this.updatePipButton();
|
||||
}
|
||||
|
||||
setupMediaControlUI(metadata, positionState) {
|
||||
this.updatePipButton();
|
||||
|
||||
if (!this.mediaControlBar.classList.contains('playing') && this._currentMediaController.isPlaying) {
|
||||
this.mediaControlBar.classList.add('playing');
|
||||
}
|
||||
|
||||
const iconURL = this._currentBrowser.mIconURL || `page-icon:${this._currentBrowser.currentURI.spec}`;
|
||||
this.mediaFocusButton.style.listStyleImage = `url(${iconURL})`;
|
||||
|
||||
this.mediaTitle.textContent = metadata.title || '';
|
||||
this.mediaArtist.textContent = metadata.artist || '';
|
||||
|
||||
gZenUIManager.updateTabsToolbar();
|
||||
gZenUIManager.restoreScrollbarState();
|
||||
|
||||
this._currentPosition = positionState.position;
|
||||
this._currentDuration = positionState.duration;
|
||||
this._currentPlaybackRate = positionState.playbackRate;
|
||||
|
||||
this.updateMediaPosition();
|
||||
|
||||
for (const key of this.supportedKeys) {
|
||||
const button = this.mediaControlBar.querySelector(`#zen-media-${key}-button`);
|
||||
button.disabled = !this._currentMediaController.supportedKeys.includes(key);
|
||||
}
|
||||
}
|
||||
|
||||
activateMediaControls(mediaController, browser) {
|
||||
this.updateMuteState();
|
||||
this.switchController();
|
||||
|
||||
if (!mediaController.isActive || this._currentBrowser?.browserId === browser.browserId) return;
|
||||
|
||||
const metadata = mediaController.getMetadata();
|
||||
const positionState = mediaController.getPositionState();
|
||||
this.mediaControllersMap.set(mediaController.id, {
|
||||
controller: mediaController,
|
||||
browser,
|
||||
position: positionState.position,
|
||||
duration: positionState.duration,
|
||||
playbackRate: positionState.playbackRate,
|
||||
lastUpdated: Date.now(),
|
||||
});
|
||||
|
||||
if (!this._currentBrowser && !this.isSharing) {
|
||||
this.setupMediaController(mediaController, browser);
|
||||
this.setupMediaControlUI(metadata, positionState);
|
||||
}
|
||||
|
||||
mediaController.addEventListener('pictureinpicturemodechange', this.onPipModeChange);
|
||||
mediaController.addEventListener('positionstatechange', this.onPositionstateChange);
|
||||
mediaController.addEventListener('playbackstatechange', this.onPlaybackstateChange);
|
||||
mediaController.addEventListener('supportedkeyschange', this.onSupportedKeysChange);
|
||||
mediaController.addEventListener('metadatachange', this.onMetadataChange);
|
||||
mediaController.addEventListener('deactivated', this.onDeactivated);
|
||||
}
|
||||
|
||||
activateMediaDeviceControls(browser) {
|
||||
if (browser?.browsingContext.currentWindowGlobal.hasActivePeerConnections()) {
|
||||
this.mediaControlBar.removeAttribute('can-pip');
|
||||
this._currentBrowser = browser;
|
||||
|
||||
const tab = window.gBrowser.getTabForBrowser(browser);
|
||||
const iconURL = browser.mIconURL || `page-icon:${browser.currentURI.spec}`;
|
||||
|
||||
this.isSharing = true;
|
||||
|
||||
this.mediaFocusButton.style.listStyleImage = `url(${iconURL})`;
|
||||
this.mediaTitle.textContent = tab.label;
|
||||
this.mediaArtist.textContent = '';
|
||||
|
||||
this.showMediaControls();
|
||||
}
|
||||
}
|
||||
|
||||
updateMediaSharing(data) {
|
||||
const { windowId, showCameraIndicator, showMicrophoneIndicator } = data;
|
||||
|
||||
for (const browser of window.gBrowser.browsers) {
|
||||
const isMatch = browser.innerWindowID === windowId;
|
||||
const isCurrentBrowser = this._currentBrowser?.browserId === browser.browserId;
|
||||
const shouldShow = showCameraIndicator || showMicrophoneIndicator;
|
||||
|
||||
if (!isMatch) continue;
|
||||
if (shouldShow && !(isCurrentBrowser && this.isSharing)) {
|
||||
const webRTC = browser.browsingContext.currentWindowGlobal.getActor('WebRTC');
|
||||
webRTC.sendAsyncMessage('webrtc:UnmuteMicrophone');
|
||||
webRTC.sendAsyncMessage('webrtc:UnmuteCamera');
|
||||
|
||||
if (this._currentBrowser) this.isSharing = false;
|
||||
if (this._currentMediaController) {
|
||||
this._currentMediaController.pause();
|
||||
this.deinitMediaController(this._currentMediaController, true, true).then(() =>
|
||||
this.activateMediaDeviceControls(browser)
|
||||
);
|
||||
} else this.activateMediaDeviceControls(browser);
|
||||
} else if (!shouldShow && isCurrentBrowser && this.isSharing) {
|
||||
this.isSharing = false;
|
||||
this._currentBrowser = null;
|
||||
this.hideMediaControls();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_onDeactivated(event) {
|
||||
this.deinitMediaController(event.target, true, event.target.id === this._currentMediaController.id, true);
|
||||
this.switchController();
|
||||
}
|
||||
|
||||
_onPlaybackstateChange() {
|
||||
if (this._currentMediaController?.isPlaying) {
|
||||
this.mediaControlBar.classList.add('playing');
|
||||
} else {
|
||||
this.switchController();
|
||||
this.mediaControlBar.classList.remove('playing');
|
||||
}
|
||||
}
|
||||
|
||||
_onSupportedKeysChange(event) {
|
||||
if (event.target.id !== this._currentMediaController?.id) return;
|
||||
for (const key of this.supportedKeys) {
|
||||
const button = this.mediaControlBar.querySelector(`#zen-media-${key}-button`);
|
||||
button.disabled = !event.target.supportedKeys.includes(key);
|
||||
}
|
||||
}
|
||||
|
||||
_onPositionstateChange(event) {
|
||||
const mediaController = this.mediaControllersMap.get(event.target.id);
|
||||
this.mediaControllersMap.set(event.target.id, {
|
||||
...mediaController,
|
||||
position: event.position,
|
||||
duration: event.duration,
|
||||
playbackRate: event.playbackRate,
|
||||
lastUpdated: Date.now(),
|
||||
});
|
||||
|
||||
if (event.target.id !== this._currentMediaController?.id) return;
|
||||
|
||||
this._currentPosition = event.position;
|
||||
this._currentDuration = event.duration;
|
||||
this._currentPlaybackRate = event.playbackRate;
|
||||
|
||||
this.updateMediaPosition();
|
||||
}
|
||||
|
||||
switchController(force = false) {
|
||||
let timeout = 3000;
|
||||
|
||||
if (this.isSharing) return;
|
||||
if (this.#isSeeking) return;
|
||||
|
||||
if (this._controllerSwitchTimeout) {
|
||||
clearTimeout(this._controllerSwitchTimeout);
|
||||
this._controllerSwitchTimeout = null;
|
||||
}
|
||||
|
||||
if (this.mediaControllersMap.size === 1) timeout = 0;
|
||||
this._controllerSwitchTimeout = setTimeout(() => {
|
||||
if (!this._currentMediaController?.isPlaying || force) {
|
||||
const nextController = Array.from(this.mediaControllersMap.values())
|
||||
.filter(
|
||||
(ctrl) =>
|
||||
ctrl.controller.isPlaying &&
|
||||
gBrowser.selectedBrowser.browserId !== ctrl.browser.browserId &&
|
||||
ctrl.controller.id !== this._currentMediaController?.id
|
||||
)
|
||||
.sort((a, b) => b.lastUpdated - a.lastUpdated)
|
||||
.shift();
|
||||
|
||||
if (nextController) {
|
||||
this.deinitMediaController(this._currentMediaController, false, true).then(() => {
|
||||
this.setupMediaController(nextController.controller, nextController.browser);
|
||||
const elapsedTime = Math.floor((Date.now() - nextController.lastUpdated) / 1000);
|
||||
|
||||
this.setupMediaControlUI(nextController.controller.getMetadata(), {
|
||||
position: nextController.position + (nextController.controller.isPlaying ? elapsedTime : 0),
|
||||
duration: nextController.duration,
|
||||
playbackRate: nextController.playbackRate,
|
||||
});
|
||||
|
||||
this.showMediaControls();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this._controllerSwitchTimeout = null;
|
||||
}, timeout);
|
||||
}
|
||||
|
||||
updateMediaPosition() {
|
||||
if (this._mediaUpdateInterval) {
|
||||
clearInterval(this._mediaUpdateInterval);
|
||||
this._mediaUpdateInterval = null;
|
||||
}
|
||||
|
||||
if (this._currentDuration >= 900_000) return this.mediaControlBar.setAttribute('media-position-hidden', 'true');
|
||||
else this.mediaControlBar.removeAttribute('media-position-hidden');
|
||||
|
||||
if (!this._currentDuration) return;
|
||||
|
||||
this.mediaCurrentTime.textContent = this.formatSecondsToTime(this._currentPosition);
|
||||
this.mediaDuration.textContent = this.formatSecondsToTime(this._currentDuration);
|
||||
this.mediaProgressBar.value = (this._currentPosition / this._currentDuration) * 100;
|
||||
|
||||
this._mediaUpdateInterval = setInterval(() => {
|
||||
if (this._currentMediaController?.isPlaying) {
|
||||
this._currentPosition += 1 * this._currentPlaybackRate;
|
||||
if (this._currentPosition > this._currentDuration) {
|
||||
this._currentPosition = this._currentDuration;
|
||||
}
|
||||
this.mediaCurrentTime.textContent = this.formatSecondsToTime(this._currentPosition);
|
||||
this.mediaProgressBar.value = (this._currentPosition / this._currentDuration) * 100;
|
||||
} else {
|
||||
clearInterval(this._mediaUpdateInterval);
|
||||
this._mediaUpdateInterval = null;
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
formatSecondsToTime(seconds) {
|
||||
if (!seconds || isNaN(seconds)) return '0:00';
|
||||
|
||||
const totalSeconds = Math.max(0, Math.ceil(seconds));
|
||||
const hours = Math.floor(totalSeconds / 3600);
|
||||
const minutes = Math.floor((totalSeconds % 3600) / 60).toString();
|
||||
const secs = (totalSeconds % 60).toString();
|
||||
|
||||
if (hours > 0) {
|
||||
return `${hours}:${minutes.padStart(2, '0')}:${secs.padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
return `${minutes}:${secs.padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
_onMetadataChange(event) {
|
||||
if (event.target.id !== this._currentMediaController?.id) return;
|
||||
this.updatePipButton();
|
||||
|
||||
const metadata = event.target.getMetadata();
|
||||
this.mediaTitle.textContent = metadata.title || '';
|
||||
this.mediaArtist.textContent = metadata.artist || '';
|
||||
|
||||
const mediaInfoElements = [this.mediaTitle, this.mediaArtist];
|
||||
for (const element of mediaInfoElements) {
|
||||
element.removeAttribute('overflow');
|
||||
}
|
||||
|
||||
this.addLabelOverflows(mediaInfoElements);
|
||||
}
|
||||
|
||||
_onPictureInPictureModeChange(event) {
|
||||
if (event.target.id !== this._currentMediaController?.id) return;
|
||||
if (event.target.isBeingUsedInPIPModeOrFullscreen) {
|
||||
this.hideMediaControls();
|
||||
this.mediaControlBar.setAttribute('pip', '');
|
||||
} else {
|
||||
const { selectedBrowser } = gBrowser;
|
||||
if (selectedBrowser.browserId !== this._currentBrowser.browserId) {
|
||||
this.showMediaControls();
|
||||
}
|
||||
|
||||
this.mediaControlBar.removeAttribute('pip');
|
||||
}
|
||||
}
|
||||
|
||||
onMediaPlayPrev() {
|
||||
if (this._currentMediaController?.supportedKeys.includes('previoustrack')) {
|
||||
this._currentMediaController.prevTrack();
|
||||
}
|
||||
}
|
||||
|
||||
onMediaPlayNext() {
|
||||
if (this._currentMediaController?.supportedKeys.includes('nexttrack')) {
|
||||
this._currentMediaController.nextTrack();
|
||||
}
|
||||
}
|
||||
|
||||
onMediaSeekDrag(event) {
|
||||
this.#isSeeking = true;
|
||||
|
||||
this._currentMediaController?.pause();
|
||||
const newTime = (event.target.value / 100) * this._currentDuration;
|
||||
this.mediaCurrentTime.textContent = this.formatSecondsToTime(newTime);
|
||||
}
|
||||
|
||||
onMediaSeekComplete(event) {
|
||||
const newPosition = (event.target.value / 100) * this._currentDuration;
|
||||
if (this._currentMediaController?.supportedKeys.includes('seekto')) {
|
||||
this._currentMediaController.seekTo(newPosition);
|
||||
this._currentMediaController.play();
|
||||
}
|
||||
|
||||
this.#isSeeking = false;
|
||||
}
|
||||
|
||||
onMediaFocus() {
|
||||
if (!this._currentBrowser) return;
|
||||
|
||||
if (this._currentMediaController) this._currentMediaController.focus();
|
||||
else if (this._currentBrowser) {
|
||||
const tab = window.gBrowser.getTabForBrowser(this._currentBrowser);
|
||||
if (tab) window.ZenWorkspaces.switchTabIfNeeded(tab);
|
||||
}
|
||||
}
|
||||
|
||||
onMediaMute() {
|
||||
if (!this.mediaControlBar.hasAttribute('muted')) {
|
||||
this._currentBrowser.mute();
|
||||
this.mediaControlBar.setAttribute('muted', '');
|
||||
} else {
|
||||
this._currentBrowser.unmute();
|
||||
this.mediaControlBar.removeAttribute('muted');
|
||||
}
|
||||
}
|
||||
|
||||
onMediaToggle() {
|
||||
if (this.mediaControlBar.classList.contains('playing')) {
|
||||
this._currentMediaController?.pause();
|
||||
} else {
|
||||
this._currentMediaController?.play();
|
||||
}
|
||||
}
|
||||
|
||||
onControllerClose() {
|
||||
if (this._currentMediaController) {
|
||||
this._currentMediaController.pause();
|
||||
this.deinitMediaController(this._currentMediaController);
|
||||
} else if (this.isSharing) this.isSharing = false;
|
||||
|
||||
this.hideMediaControls();
|
||||
this.switchController(true);
|
||||
}
|
||||
|
||||
onMediaPip() {
|
||||
this._currentBrowser.browsingContext.currentWindowGlobal
|
||||
.getActor('PictureInPictureLauncher')
|
||||
.sendAsyncMessage('PictureInPicture:KeyToggle');
|
||||
}
|
||||
|
||||
onMicrophoneMuteToggle() {
|
||||
if (this._currentBrowser) {
|
||||
const shouldMute = this.mediaControlBar.hasAttribute('mic-muted') ? 'webrtc:UnmuteMicrophone' : 'webrtc:MuteMicrophone';
|
||||
|
||||
this._currentBrowser.browsingContext.currentWindowGlobal.getActor('WebRTC').sendAsyncMessage(shouldMute);
|
||||
this.mediaControlBar.toggleAttribute('mic-muted');
|
||||
}
|
||||
}
|
||||
|
||||
onCameraMuteToggle() {
|
||||
if (this._currentBrowser) {
|
||||
const shouldMute = this.mediaControlBar.hasAttribute('camera-muted') ? 'webrtc:UnmuteCamera' : 'webrtc:MuteCamera';
|
||||
|
||||
this._currentBrowser.browsingContext.currentWindowGlobal.getActor('WebRTC').sendAsyncMessage(shouldMute);
|
||||
this.mediaControlBar.toggleAttribute('camera-muted');
|
||||
}
|
||||
}
|
||||
|
||||
updateMuteState() {
|
||||
if (!this._currentBrowser) return;
|
||||
this.mediaControlBar.toggleAttribute('muted', this._currentBrowser._audioMuted);
|
||||
}
|
||||
|
||||
updatePipButton() {
|
||||
if (!this._currentBrowser) return;
|
||||
if (this.isSharing) return;
|
||||
|
||||
const { totalPipCount, totalPipDisabled } = PictureInPicture.getEligiblePipVideoCount(this._currentBrowser);
|
||||
const canPip = totalPipCount === 1 || (totalPipDisabled > 0 && lazy.RESPECT_PIP_DISABLED);
|
||||
|
||||
this.mediaControlBar.toggleAttribute('can-pip', canPip);
|
||||
}
|
||||
}
|
||||
|
||||
window.gZenMediaController = new ZenMediaController();
|
||||
}
|
@@ -1,3 +1,9 @@
|
||||
/*
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
#zen-media-controls-toolbar {
|
||||
--progress-height: 4px;
|
||||
--button-spacing: 2px;
|
||||
@@ -19,6 +25,24 @@
|
||||
--toolbarbutton-outer-padding: 2px;
|
||||
}
|
||||
|
||||
&:not([media-sharing]) {
|
||||
#media-device-buttons {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
#media-device-buttons {
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
&[media-sharing] #zen-media-controls-hbox > toolbarbutton:not(:first-child) {
|
||||
display: none;
|
||||
|
||||
#media-device-buttons {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
&:not([can-pip]) {
|
||||
#zen-media-info-vbox {
|
||||
width: calc(100% - 26px);
|
||||
@@ -206,7 +230,7 @@
|
||||
}
|
||||
|
||||
#zen-media-info-vbox {
|
||||
#zen-media-controls-toolbar:not([media-position-hidden='true']) & {
|
||||
#zen-media-controls-toolbar:not([media-position-hidden]) & {
|
||||
transition-delay: 0.01s !important;
|
||||
}
|
||||
overflow-x: hidden;
|
||||
@@ -251,7 +275,7 @@
|
||||
align-items: center;
|
||||
padding-top: 0px !important;
|
||||
|
||||
#zen-media-controls-toolbar[media-position-hidden='true'] & {
|
||||
#zen-media-controls-toolbar[media-position-hidden] & {
|
||||
display: none;
|
||||
}
|
||||
}
|
@@ -36,6 +36,12 @@
|
||||
class="toolbarbutton-1" />
|
||||
<toolbarbutton id="zen-media-mute-button"
|
||||
class="toolbarbutton-1" />
|
||||
<hbox id="media-device-buttons">
|
||||
<toolbarbutton id="zen-media-mute-mic-button"
|
||||
class="toolbarbutton-1" />
|
||||
<toolbarbutton id="zen-media-mute-camera-button"
|
||||
class="toolbarbutton-1" />
|
||||
</hbox>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</toolbaritem>
|