initial commit
This commit is contained in:
38
README.md
Normal file
38
README.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# Bumble Electron
|
||||
|
||||
A very small Electron shell that wraps the Bumble web app so you can keep it next to the rest of your desktop messengers.
|
||||
|
||||
## Features
|
||||
- Loads the official Bumble web experience at `https://bumble.com/get-started` inside a dedicated window.
|
||||
- Blocks unexpected navigation (drag-and-drop or pop-out windows open in your default browser).
|
||||
- Single-instance enforcement so app links/notifications focus the already running window.
|
||||
- Pre-configured permissions for microphone, camera, geolocation, and notifications to match the needs of voice/video calls.
|
||||
|
||||
## Getting Started
|
||||
1. Install dependencies once:
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
2. Launch the desktop app:
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
3. Log in with your Bumble account right from the window that appears.
|
||||
|
||||
The project uses Electron only; no build step is required. If you want the window back after closing (macOS), use the dock icon or rerun `npm start`.
|
||||
|
||||
### Window behavior
|
||||
- Clicking the close button now just minimizes the window so Bumble keeps running in the background.
|
||||
- Use `Cmd+Q` (macOS) or `Ctrl+Q` (Windows/Linux) to quit the app completely.
|
||||
|
||||
## Build a Desktop Binary
|
||||
Electron Builder is preconfigured for macOS, Windows, and Linux. To create unsigned binaries for your current platform:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
Artifacts land in `dist/`. When building on macOS without a valid signing identity (or if you need to skip signing), set `CSC_IDENTITY_AUTO_DISCOVERY=false` before running the build.
|
||||
|
||||
## Packaging Notes
|
||||
The default build outputs (mac `.app`, Windows installer via NSIS, Linux AppImage/Deb) are defined in `package.json#build`. Adjust that section if you need different targets or want to point at alternative icons/resources.
|
||||
BIN
bumble_icon_512.png
Normal file
BIN
bumble_icon_512.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
42
package.json
Normal file
42
package.json
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "bumble-electron",
|
||||
"version": "1.0.0",
|
||||
"description": "Desktop Electron shell for Bumble Web.",
|
||||
"main": "src/main.js",
|
||||
"scripts": {
|
||||
"start": "electron .",
|
||||
"dev": "electron .",
|
||||
"build": "electron-builder"
|
||||
},
|
||||
"keywords": [
|
||||
"electron",
|
||||
"bumble",
|
||||
"desktop"
|
||||
],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"build": {
|
||||
"appId": "com.victorstools.bumble",
|
||||
"productName": "Bumble Desktop",
|
||||
"mac": {
|
||||
"category": "public.app-category.social-networking",
|
||||
"icon": "bumble_icon_512.png"
|
||||
},
|
||||
"win": {
|
||||
"target": "nsis",
|
||||
"icon": "bumble_icon_512.png"
|
||||
},
|
||||
"linux": {
|
||||
"target": [
|
||||
"AppImage",
|
||||
"deb"
|
||||
],
|
||||
"category": "Network",
|
||||
"icon": "bumble_icon_512.png"
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "^39.1.1",
|
||||
"electron-builder": "^26.0.12"
|
||||
}
|
||||
}
|
||||
138
src/main.js
Normal file
138
src/main.js
Normal file
@@ -0,0 +1,138 @@
|
||||
const {
|
||||
app,
|
||||
BrowserWindow,
|
||||
Menu,
|
||||
shell,
|
||||
session,
|
||||
nativeTheme,
|
||||
globalShortcut
|
||||
} = require('electron');
|
||||
const path = require('path');
|
||||
|
||||
const BUMBLE_URL = 'https://bumble.com/get-started';
|
||||
const SINGLE_INSTANCE_LOCK = app.requestSingleInstanceLock();
|
||||
const ALLOWED_PERMISSIONS = new Set(['media', 'geolocation', 'notifications']);
|
||||
const ICON_PATH = path.join(__dirname, '..', 'bumble_icon_512.png');
|
||||
|
||||
let mainWindow;
|
||||
let isQuitting = false;
|
||||
|
||||
app.setAppUserModelId('com.victorstools.bumble');
|
||||
|
||||
if (!SINGLE_INSTANCE_LOCK) {
|
||||
app.quit();
|
||||
}
|
||||
|
||||
const desktopUserAgent = `Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${process.versions.chrome} Safari/537.36`;
|
||||
|
||||
const configureSession = () => {
|
||||
const defaultSession = session.defaultSession;
|
||||
if (!defaultSession) {
|
||||
return;
|
||||
}
|
||||
|
||||
defaultSession.setPermissionRequestHandler((_, permission, callback) => {
|
||||
callback(ALLOWED_PERMISSIONS.has(permission));
|
||||
});
|
||||
|
||||
defaultSession.setUserAgent(desktopUserAgent);
|
||||
};
|
||||
|
||||
const createWindow = () => {
|
||||
if (mainWindow) {
|
||||
return mainWindow;
|
||||
}
|
||||
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 1200,
|
||||
height: 800,
|
||||
minWidth: 900,
|
||||
minHeight: 600,
|
||||
title: 'Bumble',
|
||||
backgroundColor: nativeTheme.shouldUseDarkColors ? '#16161a' : '#ffffff',
|
||||
icon: ICON_PATH,
|
||||
autoHideMenuBar: true,
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js'),
|
||||
contextIsolation: true,
|
||||
nodeIntegration: false,
|
||||
spellcheck: true,
|
||||
sandbox: false
|
||||
}
|
||||
});
|
||||
|
||||
mainWindow.loadURL(BUMBLE_URL, { userAgent: desktopUserAgent });
|
||||
|
||||
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
|
||||
shell.openExternal(url);
|
||||
return { action: 'deny' };
|
||||
});
|
||||
|
||||
mainWindow.webContents.on('will-navigate', (event, url) => {
|
||||
if (!url.startsWith('https://') && !url.startsWith('http://')) {
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
mainWindow.on('close', event => {
|
||||
if (!isQuitting) {
|
||||
event.preventDefault();
|
||||
mainWindow.minimize();
|
||||
}
|
||||
});
|
||||
|
||||
mainWindow.on('closed', () => {
|
||||
mainWindow = null;
|
||||
});
|
||||
|
||||
return mainWindow;
|
||||
};
|
||||
|
||||
if (SINGLE_INSTANCE_LOCK) {
|
||||
app.on('second-instance', () => {
|
||||
if (mainWindow) {
|
||||
if (mainWindow.isMinimized()) {
|
||||
mainWindow.restore();
|
||||
}
|
||||
mainWindow.show();
|
||||
mainWindow.focus();
|
||||
} else {
|
||||
createWindow();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
app.on('before-quit', () => {
|
||||
isQuitting = true;
|
||||
});
|
||||
|
||||
app.whenReady().then(() => {
|
||||
Menu.setApplicationMenu(null);
|
||||
configureSession();
|
||||
createWindow();
|
||||
globalShortcut.register('CommandOrControl+Q', () => {
|
||||
isQuitting = true;
|
||||
app.quit();
|
||||
});
|
||||
|
||||
app.on('activate', () => {
|
||||
if (mainWindow) {
|
||||
if (mainWindow.isMinimized()) {
|
||||
mainWindow.restore();
|
||||
}
|
||||
mainWindow.show();
|
||||
} else {
|
||||
createWindow();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
|
||||
app.on('will-quit', () => {
|
||||
globalShortcut.unregisterAll();
|
||||
});
|
||||
19
src/preload.js
Normal file
19
src/preload.js
Normal file
@@ -0,0 +1,19 @@
|
||||
const { contextBridge } = require('electron');
|
||||
|
||||
// Prevent files from being dropped into the Bumble webview, which would otherwise
|
||||
// trigger navigations away from the Bumble UI.
|
||||
window.addEventListener('dragover', event => {
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
window.addEventListener('drop', event => {
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
contextBridge.exposeInMainWorld('bumbleDesktop', {
|
||||
platform: process.platform,
|
||||
versions: {
|
||||
chrome: process.versions.chrome,
|
||||
electron: process.versions.electron
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user