mirror of
https://github.com/zhom/donutbrowser.git
synced 2026-05-04 09:35:11 +02:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7a5b807828 | |||
| d0a5c16ce9 | |||
| e2e1ad1582 | |||
| cb61861503 | |||
| 1950ef0098 | |||
| 814875c28e | |||
| b06ca4f11e |
@@ -19,16 +19,3 @@ jobs:
|
||||
uses: dependabot/fetch-metadata@v2
|
||||
with:
|
||||
github-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
|
||||
- name: Approve Dependabot PR
|
||||
run: gh pr review --approve "$PR_URL"
|
||||
env:
|
||||
PR_URL: ${{ github.event.pull_request.html_url }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Auto-merge (squash) Dependabot PR
|
||||
if: ${{ steps.dependabot-metadata.outputs.update-type != 'version-update:semver-major' }}
|
||||
run: gh pr merge --auto --squash "$PR_URL"
|
||||
env:
|
||||
PR_URL: ${{ github.event.pull_request.html_url }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
+2
-2
@@ -30,8 +30,8 @@ yarn-error.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# nodecar
|
||||
nodecar/dist
|
||||
nodecar/node_modules
|
||||
**/dist
|
||||
**/node_modules
|
||||
|
||||
# local env files
|
||||
.env*.local
|
||||
|
||||
@@ -54,6 +54,10 @@ Have questions or want to contribute? We'd love to hear from you!
|
||||
- **Issues**: [GitHub Issues](https://github.com/zhom/donutbrowser/issues)
|
||||
- **Discussions**: [GitHub Discussions](https://github.com/zhom/donutbrowser/discussions)
|
||||
|
||||
## Contact
|
||||
|
||||
Have an urgent question or want to report a security vulnerability? Send an email to contact at donutbrowser dot com and we'll get back to you as fast as possible.
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the AGPL-3.0 License - see the [LICENSE](LICENSE) file for details.
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"license": "AGPL-3.0",
|
||||
"packageManager": "pnpm@10.6.1",
|
||||
"dependencies": {
|
||||
"@types/node": "^22.15.17",
|
||||
|
||||
+3
-2
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"name": "donutbrowser",
|
||||
"private": true,
|
||||
"license": "AGPL-3.0",
|
||||
"version": "0.2.4",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
@@ -36,7 +37,7 @@
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"cmdk": "^1.1.1",
|
||||
"next": "^15.3.2",
|
||||
"next": "^15.3.3",
|
||||
"next-themes": "^0.4.6",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
@@ -61,7 +62,7 @@
|
||||
"eslint-config-next": "^15.3.2",
|
||||
"eslint-plugin-react-hooks": "^5.2.0",
|
||||
"husky": "^9.1.7",
|
||||
"lint-staged": "^15.3.0",
|
||||
"lint-staged": "^16.1.0",
|
||||
"tailwindcss": "^4.1.7",
|
||||
"tw-animate-css": "^1.3.0",
|
||||
"typescript": "~5.8.3",
|
||||
|
||||
Generated
+928
-942
File diff suppressed because it is too large
Load Diff
@@ -153,8 +153,8 @@ pub async fn open_url_with_profile(
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn smart_open_url(
|
||||
_app_handle: tauri::AppHandle,
|
||||
_url: String,
|
||||
app_handle: tauri::AppHandle,
|
||||
url: String,
|
||||
_is_startup: Option<bool>,
|
||||
) -> Result<String, String> {
|
||||
use crate::browser_runner::BrowserRunner;
|
||||
@@ -171,10 +171,75 @@ pub async fn smart_open_url(
|
||||
}
|
||||
|
||||
println!(
|
||||
"URL opening - Total profiles: {}, showing profile selector",
|
||||
"URL opening - Total profiles: {}, checking for running profiles",
|
||||
profiles.len()
|
||||
);
|
||||
|
||||
// Always show the profile selector so the user can choose
|
||||
// Check for running profiles and find the first one that can handle URLs
|
||||
for profile in &profiles {
|
||||
// Check if this profile is running
|
||||
let is_running = runner
|
||||
.check_browser_status(app_handle.clone(), profile)
|
||||
.await
|
||||
.unwrap_or(false);
|
||||
|
||||
if is_running {
|
||||
println!(
|
||||
"Found running profile '{}', attempting to open URL",
|
||||
profile.name
|
||||
);
|
||||
|
||||
// For TOR browser: Check if any other TOR browser is running
|
||||
if profile.browser == "tor-browser" {
|
||||
let mut other_tor_running = false;
|
||||
for p in &profiles {
|
||||
if p.browser == "tor-browser"
|
||||
&& p.name != profile.name
|
||||
&& runner
|
||||
.check_browser_status(app_handle.clone(), p)
|
||||
.await
|
||||
.unwrap_or(false)
|
||||
{
|
||||
other_tor_running = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if other_tor_running {
|
||||
continue; // Skip this one, can't have multiple TOR instances
|
||||
}
|
||||
}
|
||||
|
||||
// For Mullvad browser: skip if running (can't open URLs in running Mullvad)
|
||||
if profile.browser == "mullvad-browser" {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Try to open the URL with this running profile
|
||||
match runner
|
||||
.launch_or_open_url(app_handle.clone(), profile, Some(url.clone()))
|
||||
.await
|
||||
{
|
||||
Ok(_) => {
|
||||
println!(
|
||||
"Successfully opened URL '{}' with running profile '{}'",
|
||||
url, profile.name
|
||||
);
|
||||
return Ok(format!("opened_with_profile:{}", profile.name));
|
||||
}
|
||||
Err(e) => {
|
||||
println!(
|
||||
"Failed to open URL with running profile '{}': {}",
|
||||
profile.name, e
|
||||
);
|
||||
// Continue to try other profiles or show selector
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println!("No suitable running profiles found, showing profile selector");
|
||||
|
||||
// No suitable running profile found, show the profile selector
|
||||
Err("show_selector".to_string())
|
||||
}
|
||||
|
||||
+4
-6
@@ -146,10 +146,7 @@ export default function Home() {
|
||||
// Listen for show profile selector events
|
||||
await listen<string>("show-profile-selector", (event) => {
|
||||
console.log("Received show profile selector request:", event.payload);
|
||||
setPendingUrls((prev) => [
|
||||
...prev,
|
||||
{ id: Date.now().toString(), url: event.payload },
|
||||
]);
|
||||
setPendingUrls([{ id: Date.now().toString(), url: event.payload }]);
|
||||
});
|
||||
|
||||
// Listen for show create profile dialog events
|
||||
@@ -175,7 +172,7 @@ export default function Home() {
|
||||
url,
|
||||
});
|
||||
console.log("Smart URL opening succeeded:", result);
|
||||
// URL was handled successfully
|
||||
// URL was handled successfully, no need to show selector
|
||||
} catch (error: unknown) {
|
||||
console.log(
|
||||
"Smart URL opening failed or requires profile selection:",
|
||||
@@ -183,7 +180,8 @@ export default function Home() {
|
||||
);
|
||||
|
||||
// Show profile selector for manual selection
|
||||
setPendingUrls((prev) => [...prev, { id: Date.now().toString(), url }]);
|
||||
// Replace any existing pending URL with the new one
|
||||
setPendingUrls([{ id: Date.now().toString(), url }]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -69,16 +69,29 @@ export function ProfileSelectorDialog({
|
||||
|
||||
// Auto-select first available profile for link opening
|
||||
if (profileList.length > 0) {
|
||||
// Find the first profile that can be used for opening links
|
||||
const availableProfile = profileList.find((profile) => {
|
||||
return canUseProfileForLinks(profile, profileList, runningProfiles);
|
||||
// First, try to find a running profile that can be used for opening links
|
||||
const runningAvailableProfile = profileList.find((profile) => {
|
||||
const isRunning = runningProfiles.has(profile.name);
|
||||
return (
|
||||
isRunning &&
|
||||
canUseProfileForLinks(profile, profileList, runningProfiles)
|
||||
);
|
||||
});
|
||||
|
||||
if (availableProfile) {
|
||||
setSelectedProfile(availableProfile.name);
|
||||
if (runningAvailableProfile) {
|
||||
setSelectedProfile(runningAvailableProfile.name);
|
||||
} else {
|
||||
// If no suitable profile found, still select the first one to show UI
|
||||
setSelectedProfile(profileList[0].name);
|
||||
// If no running profile is suitable, find the first profile that can be used for opening links
|
||||
const availableProfile = profileList.find((profile) => {
|
||||
return canUseProfileForLinks(profile, profileList, runningProfiles);
|
||||
});
|
||||
|
||||
if (availableProfile) {
|
||||
setSelectedProfile(availableProfile.name);
|
||||
} else {
|
||||
// If no suitable profile found, still select the first one to show UI
|
||||
setSelectedProfile(profileList[0].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -277,7 +290,7 @@ export function ProfileSelectorDialog({
|
||||
!canUseForLinks ? "opacity-50" : ""
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center gap-3 p-3 rounded-lg hover:bg-accent cursor-pointer">
|
||||
<div className="flex items-center gap-3 py-1 px-2 rounded-lg hover:bg-accent cursor-pointer">
|
||||
<div className="flex items-center gap-2">
|
||||
{(() => {
|
||||
const IconComponent = getBrowserIcon(
|
||||
|
||||
Reference in New Issue
Block a user