Compare commits
39 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
e4ca9882b9 | ||
|
9c4a886799 | ||
|
6839090631 | ||
|
1232eea297 | ||
|
b88509d210 | ||
|
2f95583af1 | ||
|
6f6ab38c9f | ||
|
10887b8358 | ||
|
4ce43bdac3 | ||
|
9947bfc3dc | ||
|
b68a85ac2f | ||
|
dfbb0492ac | ||
|
def3cd312d | ||
|
5539ae2c63 | ||
|
53bf782ddc | ||
|
01e9154a33 | ||
|
04ec30066d | ||
|
8a1b2ac65f | ||
|
316f6685e0 | ||
|
d26d82121c | ||
|
cb0cfbe640 | ||
|
31731d5f24 | ||
|
6fece01fa9 | ||
|
afedc14db5 | ||
|
9d337fa315 | ||
|
f04efda911 | ||
|
3a0941c67c | ||
|
08fbe470ad | ||
|
a82d5d67e2 | ||
|
52883d335d | ||
|
93ab0b9731 | ||
|
3e86319bb8 | ||
|
baa6e33fcd | ||
|
cdb9130a3d | ||
|
d7ad3a8812 | ||
|
c28640217b | ||
|
9e2bef0037 | ||
33eb3a931f | |||
6753ed7e79 |
@@ -2,9 +2,9 @@ name: Build and Release bsky-desktop
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ $default-branch ]
|
branches: [$default-branch]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ $default-branch ]
|
branches: [$default-branch]
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
@@ -15,8 +15,6 @@ jobs:
|
|||||||
build-linux:
|
build-linux:
|
||||||
name: Build bsky-desktop (Linux)
|
name: Build bsky-desktop (Linux)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
outputs:
|
|
||||||
artifact: ${{ steps.upload-artifact.outputs.artifact }}
|
|
||||||
env:
|
env:
|
||||||
ext: "AppImage"
|
ext: "AppImage"
|
||||||
GITHUB_TOKEN: ${{ secrets.GHT }}
|
GITHUB_TOKEN: ${{ secrets.GHT }}
|
||||||
@@ -39,6 +37,19 @@ jobs:
|
|||||||
- name: Build (arm64)
|
- name: Build (arm64)
|
||||||
run: npm run build -- --arch arm64
|
run: npm run build -- --arch arm64
|
||||||
|
|
||||||
|
- name: Download appimagelint and its deps
|
||||||
|
run: |
|
||||||
|
sudo apt install fuse -y
|
||||||
|
wget https://github.com/TheAssassin/appimagelint/releases/download/continuous/appimagelint-x86_64.AppImage
|
||||||
|
chmod +x appimagelint-x86_64.AppImage
|
||||||
|
|
||||||
|
- name: Check the appimage(s)
|
||||||
|
run: ./appimagelint-x86_64.AppImage dist/*.AppImage
|
||||||
|
|
||||||
|
- name: Generate checksum
|
||||||
|
run: |
|
||||||
|
sha256sum dist/*.AppImage > sha256sum.txt
|
||||||
|
|
||||||
- name: Upload Linux Artifacts
|
- name: Upload Linux Artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
id: upload-artifact
|
id: upload-artifact
|
||||||
@@ -47,12 +58,11 @@ jobs:
|
|||||||
path: |
|
path: |
|
||||||
dist/*.AppImage
|
dist/*.AppImage
|
||||||
dist/latest*.yml
|
dist/latest*.yml
|
||||||
|
sha256sum.txt
|
||||||
|
|
||||||
build-windows:
|
build-windows:
|
||||||
name: Build bsky-desktop (Windows)
|
name: Build bsky-desktop (Windows)
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
outputs:
|
|
||||||
artifact: ${{ steps.upload-artifact.outputs.artifact }}
|
|
||||||
env:
|
env:
|
||||||
ext: "exe"
|
ext: "exe"
|
||||||
GITHUB_TOKEN: ${{ secrets.GHT }}
|
GITHUB_TOKEN: ${{ secrets.GHT }}
|
||||||
@@ -74,6 +84,10 @@ jobs:
|
|||||||
|
|
||||||
- name: Build (arm64)
|
- name: Build (arm64)
|
||||||
run: npm run build -- --arch arm64
|
run: npm run build -- --arch arm64
|
||||||
|
|
||||||
|
- name: Generate checksum
|
||||||
|
run: |
|
||||||
|
sha256sum dist/*.exe > sha256sum.txt
|
||||||
|
|
||||||
- name: Upload Windows Artifacts
|
- name: Upload Windows Artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
@@ -83,12 +97,11 @@ jobs:
|
|||||||
path: |
|
path: |
|
||||||
dist/*.exe
|
dist/*.exe
|
||||||
dist/latest*.yml
|
dist/latest*.yml
|
||||||
|
sha256sum.txt
|
||||||
|
|
||||||
build-macos:
|
build-macos:
|
||||||
name: Build bsky-desktop (macOS)
|
name: Build bsky-desktop (macOS)
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
outputs:
|
|
||||||
artifact: ${{ steps.upload-artifact.outputs.artifact }}
|
|
||||||
env:
|
env:
|
||||||
ext: "dmg"
|
ext: "dmg"
|
||||||
GITHUB_TOKEN: ${{ secrets.GHT }}
|
GITHUB_TOKEN: ${{ secrets.GHT }}
|
||||||
@@ -110,6 +123,11 @@ jobs:
|
|||||||
|
|
||||||
- name: Build (arm64)
|
- name: Build (arm64)
|
||||||
run: npm run build -- --arch arm64
|
run: npm run build -- --arch arm64
|
||||||
|
|
||||||
|
- name: Generate checksum
|
||||||
|
run: |
|
||||||
|
shasum -a 256 dist/*.dmg > sha256sum.txt
|
||||||
|
# shasum -a 256 dist/*.pkg >> sha256sum.txt
|
||||||
|
|
||||||
- name: Upload macOS Artifacts
|
- name: Upload macOS Artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
@@ -119,22 +137,25 @@ jobs:
|
|||||||
path: |
|
path: |
|
||||||
dist/*.dmg
|
dist/*.dmg
|
||||||
dist/latest*.yml
|
dist/latest*.yml
|
||||||
|
sha256sum.txt
|
||||||
|
|
||||||
release:
|
release:
|
||||||
name: Create Release
|
name: Create Release
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [build-linux, build-windows, build-macos]
|
needs: [build-linux, build-windows, build-macos]
|
||||||
|
outputs:
|
||||||
|
version_tag: ${{ steps.version.outputs.version }}
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GHT }}
|
GITHUB_TOKEN: ${{ secrets.GHT }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout git repo
|
- name: Checkout git repo
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Get app version
|
- name: Get app version
|
||||||
id: version
|
id: version
|
||||||
uses: pchynoweth/action-get-npm-version@1.1.1
|
uses: pchynoweth/action-get-npm-version@1.1.1
|
||||||
|
|
||||||
- name: Download Linux Artifacts
|
- name: Download Linux Artifacts
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
@@ -152,9 +173,13 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: macos-artifacts
|
name: macos-artifacts
|
||||||
path: dist/macos
|
path: dist/macos
|
||||||
|
|
||||||
- name: Display structure of downloaded files
|
- name: Display structure of downloaded files
|
||||||
run: ls -R dist
|
run: ls -R dist
|
||||||
|
|
||||||
|
- name: Combine checksums
|
||||||
|
run: |
|
||||||
|
cat dist/linux/sha256sum.txt dist/windows/sha256sum.txt dist/macos/sha256sum.txt > sha256sums.txt
|
||||||
|
|
||||||
- name: Upload Release
|
- name: Upload Release
|
||||||
id: create_release
|
id: create_release
|
||||||
@@ -166,4 +191,49 @@ jobs:
|
|||||||
files: |
|
files: |
|
||||||
dist/linux/*.AppImage
|
dist/linux/*.AppImage
|
||||||
dist/windows/*.exe
|
dist/windows/*.exe
|
||||||
dist/macos/*.dmg
|
dist/macos/*.dmg
|
||||||
|
sha256sums.txt
|
||||||
|
|
||||||
|
aur:
|
||||||
|
name: Publish to AUR
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: release
|
||||||
|
env:
|
||||||
|
AUR_TOKEN: ${{ secrets.AUR_TOKEN }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout git repo
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Download linux artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: linux-artifacts
|
||||||
|
path: dist/linux
|
||||||
|
|
||||||
|
- name: List downloaded files
|
||||||
|
run: ls -R dist
|
||||||
|
|
||||||
|
- name: Show content of sha256sum.txt
|
||||||
|
run: cat dist/linux/sha256sum.txt
|
||||||
|
|
||||||
|
- name: Get app version
|
||||||
|
id: version
|
||||||
|
uses: pchynoweth/action-get-npm-version@1.1.1
|
||||||
|
|
||||||
|
- name: Extract checksum from sha256sum.txt and change build version
|
||||||
|
run: |
|
||||||
|
new_checksum=$(awk 'NR==1 { print $1 }' ./dist/linux/sha256sum.txt)
|
||||||
|
sed -i "s|sha256sums=('SKIP' 'SKIP')|sha256sums=('$new_checksum' 'SKIP')|" ./build/PKGBUILD
|
||||||
|
sed -i "s/^pkgver=.*$/pkgver=${{ steps.version.outputs.version }}/" ./build/PKGBUILD
|
||||||
|
|
||||||
|
- name: Publish AUR package
|
||||||
|
uses: KSXGitHub/github-actions-deploy-aur@v3.0.1
|
||||||
|
with:
|
||||||
|
pkgname: bskydesktop
|
||||||
|
pkgbuild: ./build/PKGBUILD
|
||||||
|
commit_username: ${{ secrets.AUR_USERNAME }}
|
||||||
|
commit_email: ${{ secrets.AUR_EMAIL }}
|
||||||
|
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
|
||||||
|
commit_message: New Version
|
||||||
|
ssh_keyscan_types: rsa,ecdsa,ed25519
|
13
build/.SRCINFO
Normal file
13
build/.SRCINFO
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
pkgbase = bskydesktop
|
||||||
|
pkgdesc = Bluesky Desktop - A decentralized social networking client distributed as an AppImage
|
||||||
|
pkgver = 1.0.8
|
||||||
|
pkgrel = 1
|
||||||
|
url = https://github.com/oxmc/bsky-desktop
|
||||||
|
arch = x86_64
|
||||||
|
arch = aarch64
|
||||||
|
license = MIT
|
||||||
|
makedepends = curl
|
||||||
|
depends = fuse2
|
||||||
|
options = !strip
|
||||||
|
|
||||||
|
pkgname = bskydesktop
|
79
build/PKGBUILD
Normal file
79
build/PKGBUILD
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
# Maintainer: GizzyUwU me@gizzy.pro
|
||||||
|
# Maintainer: oxmc contact@oxmc.is-a.dev
|
||||||
|
|
||||||
|
pkgname=bskydesktop
|
||||||
|
pkgver=""
|
||||||
|
pkgrel=1
|
||||||
|
pkgdesc="Bluesky Desktop - A decentralized social networking client distributed as an AppImage"
|
||||||
|
arch=('x86_64' 'aarch64')
|
||||||
|
url="https://github.com/oxmc/bsky-desktop"
|
||||||
|
license=('AGPL-3.0-only')
|
||||||
|
depends=('fuse2')
|
||||||
|
makedepends=('curl')
|
||||||
|
options=('!strip')
|
||||||
|
icon_url="https://raw.githubusercontent.com/oxmc/bsky-desktop/refs/heads/main/src/ui/images/logo.png"
|
||||||
|
icon_name="bsky-desktop.png"
|
||||||
|
|
||||||
|
prepare() {
|
||||||
|
latest_tag=$(curl -s "https://api.github.com/repos/oxmc/bsky-desktop/releases/latest" | grep -Po '"tag_name": "\K.*?(?=")')
|
||||||
|
echo "Latest release tag: $latest_tag"
|
||||||
|
|
||||||
|
case "$CARCH" in
|
||||||
|
x86_64)
|
||||||
|
appimage_name="bskyDesktop-${latest_tag:1}-linux-x64.AppImage"
|
||||||
|
;;
|
||||||
|
aarch64)
|
||||||
|
appimage_name="bskyDesktop-${latest_tag:1}-linux-arm64.AppImage"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unsupported architecture: $CARCH"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
source=(
|
||||||
|
"https://github.com/oxmc/bsky-desktop/releases/download/$latest_tag/$appimage_name"
|
||||||
|
"$icon_url"
|
||||||
|
)
|
||||||
|
echo "AppImage source: ${source[0]}"
|
||||||
|
sha256sums=('SKIP' 'SKIP')
|
||||||
|
curl -L "${source[0]}" -o "$srcdir/bskyDesktop.appimage"
|
||||||
|
curl -L "${source[1]}" -o "$srcdir/$icon_name"
|
||||||
|
}
|
||||||
|
|
||||||
|
package() {
|
||||||
|
appimage_dest="$pkgdir/opt/appimages/bsky-desktop"
|
||||||
|
bin_dest="$pkgdir/usr/bin/bsky-desktop"
|
||||||
|
desktop_file="$pkgdir/usr/share/applications/bsky-desktop.desktop"
|
||||||
|
icon_dest="$pkgdir/usr/share/icons/hicolor/128x128/apps/$icon_name"
|
||||||
|
|
||||||
|
if [[ ! -f "$srcdir/bskyDesktop.appimage" ]]; then
|
||||||
|
echo "Error: AppImage file not found: $srcdir/bskyDesktop.appimage"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ ! -f "$srcdir/$icon_name" ]]; then
|
||||||
|
echo "Error: Icon file not found: $srcdir/$icon_name"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
install -d "$pkgdir/opt/appimages"
|
||||||
|
install -Dm755 "$srcdir/bskyDesktop.appimage" "$appimage_dest"
|
||||||
|
|
||||||
|
install -d "$(dirname "$bin_dest")"
|
||||||
|
ln -sf "/opt/appimages/bsky-desktop" "$bin_dest"
|
||||||
|
|
||||||
|
install -d "$(dirname "$icon_dest")"
|
||||||
|
install -Dm644 "$srcdir/$icon_name" "$icon_dest"
|
||||||
|
|
||||||
|
install -d "$(dirname "$desktop_file")"
|
||||||
|
install -Dm644 /dev/stdin "$desktop_file" <<EOF
|
||||||
|
[Desktop Entry]
|
||||||
|
Name=Bluesky Desktop
|
||||||
|
Comment=Bluesky Desktop Client
|
||||||
|
Exec=/usr/bin/bsky-desktop %u
|
||||||
|
Icon=bsky-desktop
|
||||||
|
Terminal=false
|
||||||
|
Type=Application
|
||||||
|
Categories=Network;Social;Application;
|
||||||
|
EOF
|
||||||
|
}
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "bsky-desktop",
|
"name": "bsky-desktop",
|
||||||
"version": "1.0.7",
|
"version": "1.0.9",
|
||||||
"description": "A desktop app of bsky.app",
|
"description": "A desktop app of bsky.app",
|
||||||
"main": "src/app/main.js",
|
"main": "src/app/main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -38,6 +38,10 @@
|
|||||||
],
|
],
|
||||||
"artifactName": "bsky-desktop.${ext}",
|
"artifactName": "bsky-desktop.${ext}",
|
||||||
"mac": {
|
"mac": {
|
||||||
|
"target": [
|
||||||
|
"dmg",
|
||||||
|
"pkg"
|
||||||
|
],
|
||||||
"icon": "src/ui/images/logo.icns",
|
"icon": "src/ui/images/logo.icns",
|
||||||
"category": "Network"
|
"category": "Network"
|
||||||
},
|
},
|
||||||
@@ -45,7 +49,7 @@
|
|||||||
"target": [
|
"target": [
|
||||||
"appimage"
|
"appimage"
|
||||||
],
|
],
|
||||||
"icon": "src/ui/images/logo.png",
|
"icon": "src/ui/images/icons",
|
||||||
"category": "Network"
|
"category": "Network"
|
||||||
},
|
},
|
||||||
"win": {
|
"win": {
|
||||||
|
108
src/app/main.js
108
src/app/main.js
@@ -1,4 +1,4 @@
|
|||||||
const { app, BrowserWindow, BrowserView, globalShortcut, ipcMain, ipcRenderer, Tray, Menu, protocol, session } = require("electron");
|
const { app, BrowserWindow, BrowserView, globalShortcut, ipcMain, Tray, Menu, protocol, session } = require("electron");
|
||||||
const electronremote = require("@electron/remote/main");
|
const electronremote = require("@electron/remote/main");
|
||||||
//const asar = require('@electron/asar');
|
//const asar = require('@electron/asar');
|
||||||
const windowStateKeeper = require("electron-window-state");
|
const windowStateKeeper = require("electron-window-state");
|
||||||
@@ -6,8 +6,8 @@ const { setupTitlebar, attachTitlebarToWindow } = require("./titlebar/main");
|
|||||||
const openAboutWindow = require("./about-window/src/index").default;
|
const openAboutWindow = require("./about-window/src/index").default;
|
||||||
const badge = require('./badge');
|
const badge = require('./badge');
|
||||||
const contextMenu = require('./context-menu');
|
const contextMenu = require('./context-menu');
|
||||||
const asarUpdater = require('./utils/asarUpdater');
|
const autoUpdater = require('./utils/auto-update');
|
||||||
//const loadCRX = require('./utils/loadCRX');
|
const loadCRX = require('./utils/loadCRX');
|
||||||
const log4js = require("log4js");
|
const log4js = require("log4js");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
@@ -36,6 +36,7 @@ global.paths = {
|
|||||||
temp: path.join(os.tmpdir(), global.appInfo.name),
|
temp: path.join(os.tmpdir(), global.appInfo.name),
|
||||||
};
|
};
|
||||||
global.paths.updateDir = path.join(global.paths.data, 'update');
|
global.paths.updateDir = path.join(global.paths.data, 'update');
|
||||||
|
global.paths.extensions = path.join(global.paths.data, 'extensions');
|
||||||
|
|
||||||
// URLs:
|
// URLs:
|
||||||
global.urls = {
|
global.urls = {
|
||||||
@@ -44,11 +45,11 @@ global.urls = {
|
|||||||
|
|
||||||
// Settings urls:
|
// Settings urls:
|
||||||
global.settings = {
|
global.settings = {
|
||||||
general: `${global.urls.main}/settings`,
|
general: `${global.urls.main}/settings`
|
||||||
account: `${global.urls.main}/settings/account`,
|
|
||||||
appearance: `${global.urls.main}/settings/appearance`,
|
|
||||||
privacy: `${global.urls.main}/settings/privacy-and-security`,
|
|
||||||
};
|
};
|
||||||
|
global.settings.account = `${global.settings.general}/account`;
|
||||||
|
global.settings.appearance = `${global.settings.general}/appearance`;
|
||||||
|
global.settings.privacy = `${global.settings.general}/privacy-and-security`;
|
||||||
|
|
||||||
// Badge options:
|
// Badge options:
|
||||||
const badgeOptions = {
|
const badgeOptions = {
|
||||||
@@ -119,6 +120,12 @@ if (!fs.existsSync(global.paths.updateDir)) {
|
|||||||
fs.mkdirSync(global.paths.updateDir, { recursive: true });
|
fs.mkdirSync(global.paths.updateDir, { recursive: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Create extensions directory if it does not exist:
|
||||||
|
if (!fs.existsSync(global.paths.extensions)) {
|
||||||
|
logger.info("Creating Extensions Directory");
|
||||||
|
fs.mkdirSync(global.paths.extensions, { recursive: true });
|
||||||
|
};
|
||||||
|
|
||||||
// improve performance on linux?
|
// improve performance on linux?
|
||||||
if (process.platform !== "win32" && process.platform !== "darwin") {
|
if (process.platform !== "win32" && process.platform !== "darwin") {
|
||||||
logger.log("Disabling Hardware Acceleration and Transparent Visuals");
|
logger.log("Disabling Hardware Acceleration and Transparent Visuals");
|
||||||
@@ -240,6 +247,34 @@ function createWindow() {
|
|||||||
// Badge count: (use mainWindow as that shows the badge on the taskbar)
|
// Badge count: (use mainWindow as that shows the badge on the taskbar)
|
||||||
new badge(mainWindow, badgeOptions);
|
new badge(mainWindow, badgeOptions);
|
||||||
|
|
||||||
|
// Load extensions (.crx files):
|
||||||
|
logger.log("Checking for extensions");
|
||||||
|
const extensions = fs.readdirSync(global.paths.extensions).filter((file) => file.endsWith('.crx'));
|
||||||
|
if (extensions.length > 0) {
|
||||||
|
logger.log(`Unpacking ${extensions.length} extensions and loading them`);
|
||||||
|
extensions.forEach((extension) => {
|
||||||
|
loadCRX(path.join(global.paths.extensions, extension));
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Check for unpacked extensions:
|
||||||
|
const unpackedExtensions = fs.readdirSync(global.paths.extensions).filter((file) => fs.lstatSync(path.join(global.paths.extensions, file)).isDirectory());
|
||||||
|
|
||||||
|
// Check if the directory contains a manifest.json file
|
||||||
|
unpackedExtensions.forEach((extension) => {
|
||||||
|
const manifestPath = path.join(global.paths.extensions, extension, 'manifest.json');
|
||||||
|
if (fs.existsSync(manifestPath)) {
|
||||||
|
logger.log(`Loading unpacked extension: ${extension}`);
|
||||||
|
session.defaultSession.loadExtension(path.join(global.paths.extensions, extension)).then(({ id }) => {
|
||||||
|
logger.log(`Extension loaded with ID: ${id}`);
|
||||||
|
}).catch((error) => {
|
||||||
|
logger.error(`Failed to load extension: ${error}`);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
logger.warn(`Skipping directory ${extension} as it does not contain a manifest.json file`);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
logger.log("Main Window Created, Showing splashscreen");
|
logger.log("Main Window Created, Showing splashscreen");
|
||||||
splash.show();
|
splash.show();
|
||||||
//mainWindow.show();
|
//mainWindow.show();
|
||||||
@@ -483,64 +518,7 @@ app.whenReady().then(() => {
|
|||||||
|
|
||||||
// Initialize the updater:
|
// Initialize the updater:
|
||||||
logger.log("Initializing Updater");
|
logger.log("Initializing Updater");
|
||||||
asarUpdater.init();
|
autoUpdater();
|
||||||
|
|
||||||
// updater events:
|
|
||||||
asarUpdater.on('available', (task) => {
|
|
||||||
//console.log('Update availible for', task)
|
|
||||||
logger.log("Update availible for", task.name);
|
|
||||||
global.PageView.webContents.send('ui:notif', JSON.stringify({ title: 'Update', message: 'An update is available' }));
|
|
||||||
if (global.splash) global.splash.webContents.send('ui:progtext', { title: 'Update Available', subtitle: 'An update is available! Downloading...' });
|
|
||||||
global.isUpdating = true;
|
|
||||||
});
|
|
||||||
asarUpdater.on('not-available', (task) => {
|
|
||||||
//console.log('not-available', task);
|
|
||||||
logger.log("No Updates Available for", task);
|
|
||||||
});
|
|
||||||
asarUpdater.on('progress', (task, p) => {
|
|
||||||
console.log(task.name, p);
|
|
||||||
if (global.splash) global.splash.webContents.send('ui:progtext', { title: 'Downloading Update', subtitle: 'Downloading update...' });
|
|
||||||
if (global.splash) global.splash.webContents.send('ui:progbar', { reason: 'update', prog: p });
|
|
||||||
});
|
|
||||||
asarUpdater.on('downloaded', (task) => {
|
|
||||||
//console.log('downloaded', task);
|
|
||||||
logger.log("Downloaded Update for,", task.name);
|
|
||||||
global.PageView.webContents.send('ui:notif', JSON.stringify({ title: 'Update Downloaded', message: 'Restarting to apply update...' }));
|
|
||||||
if (global.splash) global.splash.webContents.send('ui:progtext', { title: 'Update Downloaded', subtitle: 'Restarting to apply update...' });
|
|
||||||
});
|
|
||||||
asarUpdater.on('completed', (manifest, tasks) => {
|
|
||||||
console.log('completed', manifest, tasks);
|
|
||||||
if (tasks.length === 0) {
|
|
||||||
setTimeout(() => {
|
|
||||||
logger.log("Quitting and Installing Update");
|
|
||||||
asarUpdater.quitAndInstall();
|
|
||||||
}, 5000);
|
|
||||||
};
|
|
||||||
//app.quit()
|
|
||||||
});
|
|
||||||
asarUpdater.on('error', (err) => {
|
|
||||||
//console.error(err);
|
|
||||||
logger.error(err);
|
|
||||||
//app.quit()
|
|
||||||
});
|
|
||||||
|
|
||||||
// Set the feed URL (only works in packaged app):
|
|
||||||
if (app.isPackaged) {
|
|
||||||
logger.log("Setting Feed URL for app.asar");
|
|
||||||
asarUpdater.setFeedURL(path.join(global.paths.app_root), 'https://cdn.oxmc.me/internal/bsky-desktop/update/core');
|
|
||||||
};
|
|
||||||
|
|
||||||
//Check for updates:
|
|
||||||
logger.log("Checking for Updates");
|
|
||||||
if (app.isPackaged) {
|
|
||||||
const UPDATE_CHECK = 1000 * 60 * 60 * 4 // 4 hours
|
|
||||||
setInterval(() => {
|
|
||||||
//asarUpdater.checkForUpdates();
|
|
||||||
}, UPDATE_CHECK);
|
|
||||||
//asarUpdater.checkForUpdates();
|
|
||||||
} else {
|
|
||||||
logger.warn("Not checking for updates as app is not packaged");
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle ipc for render:
|
// Handle ipc for render:
|
||||||
ipcMain.on('close-app', (event, arg) => {
|
ipcMain.on('close-app', (event, arg) => {
|
||||||
|
157
src/app/utils/auto-update.js
Normal file
157
src/app/utils/auto-update.js
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
const path = require('path');
|
||||||
|
const os = require('os');
|
||||||
|
const fs = require('fs');
|
||||||
|
const childProcess = require('child_process');
|
||||||
|
const { app } = require('electron');
|
||||||
|
const log4js = require('log4js');
|
||||||
|
|
||||||
|
// import the asarUpdater module
|
||||||
|
const asarUpdater = require('./asarUpdater');
|
||||||
|
|
||||||
|
// Get system information
|
||||||
|
const SystemInfo = require('./sysInfo');
|
||||||
|
|
||||||
|
// Get the current system platform
|
||||||
|
const sys = new SystemInfo();
|
||||||
|
|
||||||
|
// Setup the logger
|
||||||
|
const logger = log4js.getLogger("bskydesktop");
|
||||||
|
|
||||||
|
function asarUpdate() {
|
||||||
|
asarUpdater.init();
|
||||||
|
|
||||||
|
// updater events:
|
||||||
|
asarUpdater.on('available', (task) => {
|
||||||
|
//console.log('Update availible for', task)
|
||||||
|
logger.log("Update availible for", task.name);
|
||||||
|
global.PageView.webContents.send('ui:notif', JSON.stringify({ title: 'Update', message: 'An update is available' }));
|
||||||
|
if (global.splash) global.splash.webContents.send('ui:progtext', { title: 'Update Available', subtitle: 'An update is available! Downloading...' });
|
||||||
|
global.isUpdating = true;
|
||||||
|
});
|
||||||
|
asarUpdater.on('not-available', (task) => {
|
||||||
|
//console.log('not-available', task);
|
||||||
|
logger.log("No Updates Available for", task);
|
||||||
|
});
|
||||||
|
asarUpdater.on('progress', (task, p) => {
|
||||||
|
console.log(task.name, p);
|
||||||
|
if (global.splash) global.splash.webContents.send('ui:progtext', { title: 'Downloading Update', subtitle: 'Downloading update...' });
|
||||||
|
if (global.splash) global.splash.webContents.send('ui:progbar', { reason: 'update', prog: p });
|
||||||
|
});
|
||||||
|
asarUpdater.on('downloaded', (task) => {
|
||||||
|
//console.log('downloaded', task);
|
||||||
|
logger.log("Downloaded Update for,", task.name);
|
||||||
|
global.PageView.webContents.send('ui:notif', JSON.stringify({ title: 'Update Downloaded', message: 'Restarting to apply update...' }));
|
||||||
|
if (global.splash) global.splash.webContents.send('ui:progtext', { title: 'Update Downloaded', subtitle: 'Restarting to apply update...' });
|
||||||
|
});
|
||||||
|
asarUpdater.on('completed', (manifest, tasks) => {
|
||||||
|
console.log('completed', manifest, tasks);
|
||||||
|
if (tasks.length === 0) {
|
||||||
|
setTimeout(() => {
|
||||||
|
logger.log("Quitting and Installing Update");
|
||||||
|
asarUpdater.quitAndInstall();
|
||||||
|
}, 5000);
|
||||||
|
};
|
||||||
|
//app.quit()
|
||||||
|
});
|
||||||
|
asarUpdater.on('error', (err) => {
|
||||||
|
//console.error(err);
|
||||||
|
logger.error(err);
|
||||||
|
//app.quit()
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set the feed URL (only works in packaged app):
|
||||||
|
if (app.isPackaged) {
|
||||||
|
logger.log("Setting Feed URL for app.asar");
|
||||||
|
asarUpdater.setFeedURL(path.join(global.paths.app_root), 'https://cdn.oxmc.me/internal/bsky-desktop/update/core');
|
||||||
|
};
|
||||||
|
|
||||||
|
//Check for updates:
|
||||||
|
logger.log("Checking for Updates");
|
||||||
|
if (app.isPackaged) {
|
||||||
|
const UPDATE_CHECK = 1000 * 60 * 60 * 4 // 4 hours
|
||||||
|
setInterval(() => {
|
||||||
|
//asarUpdater.checkForUpdates();
|
||||||
|
}, UPDATE_CHECK);
|
||||||
|
//asarUpdater.checkForUpdates();
|
||||||
|
} else {
|
||||||
|
logger.warn("Not checking for updates as app is not packaged");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkForUpdates() {
|
||||||
|
// Current system information
|
||||||
|
logger.log('Current system information:', sys.platform, sys.getVersion());
|
||||||
|
|
||||||
|
// Check if the current system is Windows
|
||||||
|
if (sys.isWin()) {
|
||||||
|
// Check if the system is before Windows 10
|
||||||
|
if (sys.earlierThan('10.0.0')) {
|
||||||
|
// Windows 10 and above are supported, but windows 7 and 8 are not supported
|
||||||
|
logger.error('Windows 7 and 8 are not supported, please upgrade to Windows 10 or above, not updating...');
|
||||||
|
} else {
|
||||||
|
// Check for updates, and if there are updates, download and install them
|
||||||
|
logger.log('Checking for updates (win)...');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the current system is macOS
|
||||||
|
if (sys.isMac()) {
|
||||||
|
let macArch = '';
|
||||||
|
// Check the current version of macOS, and whether we can use the pkg installer
|
||||||
|
if (sys.laterThan('10.0.0')) {
|
||||||
|
// Check if system is after macOS 10 (11, 12, etc.)
|
||||||
|
if (sys.laterThan('11.0.0')) {
|
||||||
|
// macOS 11 and above support ARM64, check if system is ARM64
|
||||||
|
logger.log('Checkking system architecture...');
|
||||||
|
if (sys.isARM64()) {
|
||||||
|
// System is ARM64 (mac-arm64)
|
||||||
|
macArch = 'arm64';
|
||||||
|
} else {
|
||||||
|
// System is x64 (mac-x64)
|
||||||
|
macArch = 'x64';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// macOS 10 is mostly x64, but some versions are ARM64
|
||||||
|
macArch = 'x64';
|
||||||
|
}
|
||||||
|
logger.log('System architecture:', macArch);
|
||||||
|
// Check for updates, and if there are updates, download and install them
|
||||||
|
logger.log('Checking for updates (mac)...');
|
||||||
|
|
||||||
|
// Run the .pkg installer
|
||||||
|
const pkgPath = path.join(global.paths.updateDir, 'bsky-desktop.pkg');
|
||||||
|
const command = `sudo installer -pkg ${pkgPath} -target /`;
|
||||||
|
|
||||||
|
// Spawn a new shell
|
||||||
|
/*const shellProcess = spawn('sh', ['-c', command], {
|
||||||
|
stdio: 'inherit', // Pipe input/output to/from the shell
|
||||||
|
});
|
||||||
|
|
||||||
|
shellProcess.on('error', (err) => {
|
||||||
|
console.error('Failed to spawn shell:', err);
|
||||||
|
});
|
||||||
|
|
||||||
|
shellProcess.on('close', (code) => {
|
||||||
|
if (code === 0) {
|
||||||
|
console.log('Update installed successfully.');
|
||||||
|
} else {
|
||||||
|
console.error(`Shell process exited with code ${code}.`);
|
||||||
|
}
|
||||||
|
});*/
|
||||||
|
} else {
|
||||||
|
// macOS versions before 10 are not supported
|
||||||
|
logger.error('macOS versions before 10 are not supported, not updating...');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the current system is Linux
|
||||||
|
if (sys.isLinux()) {
|
||||||
|
// Check for updates, and if there are updates, download and install them (no system version check)
|
||||||
|
// Linux versions use AppImage, so we instead need to check for a new asar file so that the app can
|
||||||
|
// load the new asar instead of the packaged one (or even just delete the old appimage and download a new one)
|
||||||
|
logger.log('Checking for updates (linux)...');
|
||||||
|
asarUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = checkForUpdates;
|
@@ -3,30 +3,91 @@ const path = require('path');
|
|||||||
const { session } = require('electron');
|
const { session } = require('electron');
|
||||||
const AdmZip = require('adm-zip');
|
const AdmZip = require('adm-zip');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a CRX file buffer to a ZIP buffer.
|
||||||
|
* @param {Buffer} buf - The CRX file buffer.
|
||||||
|
* @returns {Buffer} - The ZIP buffer extracted from the CRX file.
|
||||||
|
*/
|
||||||
|
function crxToZip(buf) {
|
||||||
|
function calcLength(a, b, c, d) {
|
||||||
|
let length = 0;
|
||||||
|
length += a << 0;
|
||||||
|
length += b << 8;
|
||||||
|
length += c << 16;
|
||||||
|
length += (d << 24) >>> 0;
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the file is already a ZIP file
|
||||||
|
if (buf[0] === 80 && buf[1] === 75 && buf[2] === 3 && buf[3] === 4) {
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate CRX magic number
|
||||||
|
if (buf[0] !== 67 || buf[1] !== 114 || buf[2] !== 50 || buf[3] !== 52) {
|
||||||
|
throw new Error('Invalid CRX file: Missing Cr24 magic number');
|
||||||
|
}
|
||||||
|
|
||||||
|
const version = buf[4];
|
||||||
|
const isV2 = version === 2;
|
||||||
|
const isV3 = version === 3;
|
||||||
|
|
||||||
|
if ((!isV2 && !isV3) || buf[5] || buf[6] || buf[7]) {
|
||||||
|
throw new Error('Unsupported CRX format version.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isV2) {
|
||||||
|
const publicKeyLength = calcLength(buf[8], buf[9], buf[10], buf[11]);
|
||||||
|
const signatureLength = calcLength(buf[12], buf[13], buf[14], buf[15]);
|
||||||
|
const zipStartOffset = 16 + publicKeyLength + signatureLength;
|
||||||
|
return buf.slice(zipStartOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
const headerSize = calcLength(buf[8], buf[9], buf[10], buf[11]);
|
||||||
|
const zipStartOffset = 12 + headerSize;
|
||||||
|
return buf.slice(zipStartOffset);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unpacks a .crx file and loads it as an Electron extension.
|
* Unpacks a .crx file and loads it as an Electron extension.
|
||||||
* @param {string} crxPath - Path to the .crx file.
|
* @param {string} crxPath - Path to the .crx file.
|
||||||
* @returns {Promise<string>} - Resolves with the extension ID after loading.
|
* @returns {Promise<string>} - Resolves with the extension ID after loading.
|
||||||
*/
|
*/
|
||||||
async function loadCRX(crxPath) {
|
async function loadCRX(crxPath) {
|
||||||
const outputDir = path.join(__dirname, 'extensions', path.basename(crxPath, '.crx'));
|
const outputDir = path.join(global.paths.extensions, path.basename(crxPath, '.crx'));
|
||||||
|
|
||||||
// Ensure the output directory exists
|
// Ensure the output directory exists
|
||||||
if (!fs.existsSync(outputDir)) {
|
if (!fs.existsSync(outputDir)) {
|
||||||
fs.mkdirSync(outputDir, { recursive: true });
|
fs.mkdirSync(outputDir, { recursive: true });
|
||||||
|
|
||||||
// Extract the .crx file
|
// Read the CRX file
|
||||||
const crxData = fs.readFileSync(crxPath);
|
const crxData = fs.readFileSync(crxPath);
|
||||||
const crxHeaderSize = crxData.readUInt32LE(8); // Extract header size from CRX
|
|
||||||
const zipData = crxData.slice(crxHeaderSize);
|
|
||||||
|
|
||||||
// Save the ZIP content
|
// Convert CRX to ZIP
|
||||||
|
const zipData = crxToZip(crxData);
|
||||||
|
|
||||||
|
// Extract ZIP using AdmZip
|
||||||
const zip = new AdmZip(zipData);
|
const zip = new AdmZip(zipData);
|
||||||
zip.extractAllTo(outputDir, true);
|
zip.getEntries().forEach((entry) => {
|
||||||
|
const fullPath = path.join(outputDir, entry.entryName);
|
||||||
|
|
||||||
|
if (entry.isDirectory) {
|
||||||
|
fs.mkdirSync(fullPath, { recursive: true });
|
||||||
|
} else {
|
||||||
|
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
|
||||||
|
fs.writeFileSync(fullPath, entry.getData());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the unpacked extension into Electron
|
// Load the unpacked extension into Electron
|
||||||
try {
|
try {
|
||||||
|
// Check for manifest.json
|
||||||
|
const manifestPath = path.join(outputDir, 'manifest.json');
|
||||||
|
if (!fs.existsSync(manifestPath)) {
|
||||||
|
throw new Error('Extension is missing manifest.json');
|
||||||
|
};
|
||||||
|
// Load the extension
|
||||||
const { id } = await session.defaultSession.loadExtension(outputDir);
|
const { id } = await session.defaultSession.loadExtension(outputDir);
|
||||||
console.log(`Extension loaded with ID: ${id}`);
|
console.log(`Extension loaded with ID: ${id}`);
|
||||||
return id;
|
return id;
|
||||||
|
@@ -5,6 +5,7 @@ class SystemInfo {
|
|||||||
constructor() {
|
constructor() {
|
||||||
this.platform = os.platform(); // 'win32', 'darwin', 'linux'
|
this.platform = os.platform(); // 'win32', 'darwin', 'linux'
|
||||||
this.release = os.release(); // OS version
|
this.release = os.release(); // OS version
|
||||||
|
this.arch = os.arch(); // 'arm', 'arm64', 'x64', 'x86'
|
||||||
this.versionInfo = this._getVersionInfo(); // Parsed version
|
this.versionInfo = this._getVersionInfo(); // Parsed version
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,6 +24,26 @@ class SystemInfo {
|
|||||||
return this.platform === 'linux';
|
return this.platform === 'linux';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if current system architecture is ARM
|
||||||
|
isARM() {
|
||||||
|
return this.arch === 'arm';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if current system architecture is ARM64
|
||||||
|
isARM64() {
|
||||||
|
return this.arch === 'arm64';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if current system architecture is x64
|
||||||
|
isX64() {
|
||||||
|
return this.arch === 'x64';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if current system architecture is x86
|
||||||
|
isX86() {
|
||||||
|
return this.arch === 'x86';
|
||||||
|
}
|
||||||
|
|
||||||
// Compare if current version is later than the given version
|
// Compare if current version is later than the given version
|
||||||
laterThan(compareVersion) {
|
laterThan(compareVersion) {
|
||||||
const current = this.versionInfo;
|
const current = this.versionInfo;
|
||||||
@@ -35,6 +56,11 @@ class SystemInfo {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compare if current version is earlier than the given version
|
||||||
|
earlierThan(compareVersion) {
|
||||||
|
return !this.laterThan(compareVersion);
|
||||||
|
}
|
||||||
|
|
||||||
// Private: Parse version strings (e.g., "10.0.19045" -> [10, 0, 19045])
|
// Private: Parse version strings (e.g., "10.0.19045" -> [10, 0, 19045])
|
||||||
_parseVersion(version) {
|
_parseVersion(version) {
|
||||||
return version.split('.').map((num) => parseInt(num, 10) || 0);
|
return version.split('.').map((num) => parseInt(num, 10) || 0);
|
||||||
@@ -57,13 +83,20 @@ class SystemInfo {
|
|||||||
return [0, 0, 0]; // Unknown system
|
return [0, 0, 0]; // Unknown system
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get current version as a string (e.g., "10.15.7")
|
||||||
|
getVersion() {
|
||||||
|
return this.versionInfo.join('.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = SystemInfo;
|
||||||
|
|
||||||
// Usage Example
|
// Usage Example
|
||||||
//const sys = new SystemInfo();
|
//const sys = new SystemInfo();
|
||||||
//console.log(`Is Windows: ${sys.isWin()}`);
|
//console.log(`Is Windows: ${sys.isWin()}`);
|
||||||
//console.log(`Is macOS: ${sys.isMac()}`);
|
//console.log(`Is macOS: ${sys.isMac()}`);
|
||||||
//console.log(`Is Linux: ${sys.isLinux()}`);
|
//console.log(`Is Linux: ${sys.isLinux()}`);
|
||||||
//console.log(`Current Version Info: ${sys.versionInfo.join('.')}`);
|
//console.log(`Current Version Info: ${sys.getVersion()}`);
|
||||||
//console.log(`Later than 10.0.19044: ${sys.laterThan('10.0.19044')}`);
|
//console.log(`Later than 10.0.19044: ${sys.laterThan('10.0.19044')}`);
|
||||||
//console.log(`Later than 5.15.0 (Linux Kernel): ${sys.laterThan('5.15.0')}`);
|
//console.log(`Later than 5.15.0 (Linux Kernel): ${sys.laterThan('5.15.0')}`);
|
BIN
src/ui/images/icons/128x128.png
Normal file
BIN
src/ui/images/icons/128x128.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
BIN
src/ui/images/icons/16x16.png
Normal file
BIN
src/ui/images/icons/16x16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 538 B |
BIN
src/ui/images/icons/256x256.png
Normal file
BIN
src/ui/images/icons/256x256.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.8 KiB |
BIN
src/ui/images/icons/32x32.png
Normal file
BIN
src/ui/images/icons/32x32.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 939 B |
BIN
src/ui/images/icons/48x48.png
Normal file
BIN
src/ui/images/icons/48x48.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
BIN
src/ui/images/icons/64x64.png
Normal file
BIN
src/ui/images/icons/64x64.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
@@ -374,6 +374,15 @@ const BskyExt = {
|
|||||||
},
|
},
|
||||||
"regex": /discord\.com\/invite\/([a-zA-Z0-9_]+)/
|
"regex": /discord\.com\/invite\/([a-zA-Z0-9_]+)/
|
||||||
},
|
},
|
||||||
|
"discord_profile": {
|
||||||
|
"name": "Discord",
|
||||||
|
"type": "social",
|
||||||
|
"icon": "fab fa-discord",
|
||||||
|
"brand": {
|
||||||
|
"color": "#7289DA",
|
||||||
|
},
|
||||||
|
"regex": /discord\.com\/users\/([a-zA-Z0-9_]+)/
|
||||||
|
},
|
||||||
"discord.gg": {
|
"discord.gg": {
|
||||||
"name": "Discord",
|
"name": "Discord",
|
||||||
"type": "messaging",
|
"type": "messaging",
|
||||||
@@ -473,6 +482,33 @@ const BskyExt = {
|
|||||||
},
|
},
|
||||||
"regex": /irc:\/\/([a-zA-Z0-9_]+)/
|
"regex": /irc:\/\/([a-zA-Z0-9_]+)/
|
||||||
},
|
},
|
||||||
|
"itchio": {
|
||||||
|
"name": "Itch.io",
|
||||||
|
"type": "content",
|
||||||
|
"icon": "fab fa-itch-io",
|
||||||
|
"brand": {
|
||||||
|
"color": "#FA5C5C",
|
||||||
|
},
|
||||||
|
"regex": /([a-zA-Z0-9_]+)\.itch\.io/
|
||||||
|
},
|
||||||
|
"etsy_shop": {
|
||||||
|
"name": "Etsy",
|
||||||
|
"type": "content",
|
||||||
|
"icon": "fab fa-etsy",
|
||||||
|
"brand": {
|
||||||
|
"color": "#D5641C",
|
||||||
|
},
|
||||||
|
"regex": /etsy\.com\/shop\/([a-zA-Z0-9_]+)/
|
||||||
|
},
|
||||||
|
"etsy_user": {
|
||||||
|
"name": "Etsy",
|
||||||
|
"type": "content",
|
||||||
|
"icon": "fab fa-etsy",
|
||||||
|
"brand": {
|
||||||
|
"color": "#D5641C",
|
||||||
|
},
|
||||||
|
"regex": /([a-zA-Z0-9_]+)\.etsy\.com/
|
||||||
|
},
|
||||||
"email": {
|
"email": {
|
||||||
"name": "Email",
|
"name": "Email",
|
||||||
"type": "messaging",
|
"type": "messaging",
|
||||||
@@ -498,7 +534,43 @@ const BskyExt = {
|
|||||||
"brand": {
|
"brand": {
|
||||||
"color": "#1DA1F2",
|
"color": "#1DA1F2",
|
||||||
},
|
},
|
||||||
"regex": /twitter\.com\/([a-zA-Z0-9_]+)/
|
"regex": /(twitter\.com|x\.com)\/([a-zA-Z0-9_]+)\/?$/
|
||||||
|
},
|
||||||
|
"xbox": {
|
||||||
|
"name": "Xbox",
|
||||||
|
"type": "social",
|
||||||
|
"icon": "fab fa-xbox",
|
||||||
|
"brand": {
|
||||||
|
"color": "#107C10",
|
||||||
|
},
|
||||||
|
"regex": /xbox\.com\/([a-zA-Z0-9_]+)/
|
||||||
|
},
|
||||||
|
"playstation": {
|
||||||
|
"name": "PlayStation",
|
||||||
|
"type": "social",
|
||||||
|
"icon": "fab fa-playstation",
|
||||||
|
"brand": {
|
||||||
|
"color": "#003087",
|
||||||
|
},
|
||||||
|
"regex": /playstation\.com\/([a-zA-Z0-9_]+)/
|
||||||
|
},
|
||||||
|
"steam": {
|
||||||
|
"name": "Steam",
|
||||||
|
"type": "content",
|
||||||
|
"icon": "fab fa-steam",
|
||||||
|
"brand": {
|
||||||
|
"color": "#000000",
|
||||||
|
},
|
||||||
|
"regex": /steamcommunity\.com\/id\/([a-zA-Z0-9_]+)/
|
||||||
|
},
|
||||||
|
"tiktok": {
|
||||||
|
"name": "TikTok",
|
||||||
|
"type": "social",
|
||||||
|
"icon": "fab fa-tiktok",
|
||||||
|
"brand": {
|
||||||
|
"color": "#000000",
|
||||||
|
},
|
||||||
|
"regex": /tiktok\.com\/@([a-zA-Z0-9_]+)/
|
||||||
},
|
},
|
||||||
"instagram": {
|
"instagram": {
|
||||||
"name": "Instagram",
|
"name": "Instagram",
|
||||||
@@ -729,6 +801,72 @@ const BskyExt = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constant {Object} linkStylesOverrides - Style overrides for specific link types
|
||||||
|
*/
|
||||||
|
linkStylesOverrides: {
|
||||||
|
"bluesky": {
|
||||||
|
"default": {
|
||||||
|
"color": "rgb(0, 133, 255)",
|
||||||
|
"background": "#0000",
|
||||||
|
"border": "#0000",
|
||||||
|
},
|
||||||
|
"hover": {
|
||||||
|
"color": "#fff",
|
||||||
|
"background": "#0000",
|
||||||
|
"border": "#0000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"discord": {
|
||||||
|
"default": {
|
||||||
|
"color": "#FFFFFF",
|
||||||
|
"background": "#7289DA",
|
||||||
|
"border": "#7289DA",
|
||||||
|
},
|
||||||
|
"hover": {
|
||||||
|
"color": "#7289DA",
|
||||||
|
"background": "#FFFFFF",
|
||||||
|
"border": "#7289DA"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"linktree": {
|
||||||
|
"default": {
|
||||||
|
"color": "#FFFFFF",
|
||||||
|
"background": "#39e09b",
|
||||||
|
"border": "#39e09b",
|
||||||
|
},
|
||||||
|
"hover": {
|
||||||
|
"color": "#39e09b",
|
||||||
|
"background": "#FFFFFF",
|
||||||
|
"border": "#39e09b"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"carrd": {
|
||||||
|
"default": {
|
||||||
|
"color": "#FFFFFF",
|
||||||
|
"background": "#2C2F33",
|
||||||
|
"border": "#2C2F33",
|
||||||
|
},
|
||||||
|
"hover": {
|
||||||
|
"color": "#2C2F33",
|
||||||
|
"background": "#FFFFFF",
|
||||||
|
"border": "#2C2F33"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dribbble": {
|
||||||
|
"default": {
|
||||||
|
"color": "#FFFFFF",
|
||||||
|
"background": "#EA4C89",
|
||||||
|
"border": "#EA4C89",
|
||||||
|
},
|
||||||
|
"hover": {
|
||||||
|
"color": "#EA4C89",
|
||||||
|
"background": "#FFFFFF",
|
||||||
|
"border": "#EA4C89"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @constant {Object} buttonStyles - The button styles for the supported messaging apps
|
* @constant {Object} buttonStyles - The button styles for the supported messaging apps
|
||||||
*
|
*
|
||||||
@@ -1109,7 +1247,7 @@ const BskyExt = {
|
|||||||
let header = bio.closest("[data-testid='profileView']");
|
let header = bio.closest("[data-testid='profileView']");
|
||||||
|
|
||||||
// Get the profile header button group element
|
// Get the profile header button group element
|
||||||
let buttonGroup = header.querySelector('[role="button"]').parentElement;
|
let buttonGroup = header.querySelector("div.css-175oi2r.r-2llsf > div:nth-child(1) > div > div:nth-child(2) > div.css-175oi2r.r-12vffkv");
|
||||||
|
|
||||||
// Check if the profile header button group element exists
|
// Check if the profile header button group element exists
|
||||||
if (!buttonGroup) {
|
if (!buttonGroup) {
|
||||||
|
Reference in New Issue
Block a user