Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src-tauri/src/constants.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pub const MAIN_WINDOW_LABEL: &str = "main";
pub const POPOUT_WINDOW_LABEL_PREFIX: &str = "popout";
pub const APP_TITLE: &str = "LiveSplit One";
pub const INDEX_HTML: &str = "index.html";
pub const ABOUT_BLANK: &str = "about:blank";
pub const MAIN_WINDOW_WIDTH: f64 = 850.0;
pub const MAIN_WINDOW_HEIGHT: f64 = 750.0;
57 changes: 54 additions & 3 deletions src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ use std::{
borrow::Cow,
future::Future,
str::FromStr,
sync::{Arc, RwLock},
sync::{
atomic::{AtomicUsize, Ordering},
Arc, RwLock,
},
};

use livesplit_core::{
Expand All @@ -13,7 +16,15 @@ use livesplit_core::{
networking::server_protocol::Command,
HotkeyConfig, HotkeySystem, TimeSpan, TimingMethod,
};
use tauri::{Emitter, Manager, WebviewWindow};
use tauri::{
webview::NewWindowResponse, Emitter, Manager, WebviewUrl, WebviewWindow, WebviewWindowBuilder,
};

mod constants;
use constants::{
ABOUT_BLANK, APP_TITLE, INDEX_HTML, MAIN_WINDOW_HEIGHT, MAIN_WINDOW_LABEL, MAIN_WINDOW_WIDTH,
POPOUT_WINDOW_LABEL_PREFIX,
};

struct State {
hotkey_system: RwLock<Option<HotkeySystem<TauriCommandSink>>>,
Expand Down Expand Up @@ -214,7 +225,47 @@ fn main() {
window: RwLock::new(None),
})
.setup(move |app| {
let main_window = app.webview_windows().values().next().unwrap().clone();
let app_handle = app.handle().clone();
let popout_counter = Arc::new(AtomicUsize::new(0));
let popout_counter_for_handler = popout_counter.clone();

let main_window = WebviewWindowBuilder::new(
app,
MAIN_WINDOW_LABEL,
WebviewUrl::App(INDEX_HTML.into()),
)
.title(APP_TITLE)
.inner_size(MAIN_WINDOW_WIDTH, MAIN_WINDOW_HEIGHT)
.use_https_scheme(true)
// WebKitGTK can return `null` for the browser-managed `window.open`
// flow. Creating the requested window here keeps the frontend code
// portable while giving Tauri full control over Linux popouts.
.on_new_window(move |_url, features| {
let label = format!(
"{POPOUT_WINDOW_LABEL_PREFIX}-{}",
popout_counter_for_handler.fetch_add(1, Ordering::Relaxed)
);
let builder = WebviewWindowBuilder::new(
&app_handle,
label,
WebviewUrl::External(ABOUT_BLANK.parse().unwrap()),
)
.window_features(features)
.on_document_title_changed(|window, title| {
let _ = window.set_title(&title);
})
.title(APP_TITLE);

match builder.build() {
Ok(window) => NewWindowResponse::Create { window },
Err(err) => {
eprintln!("failed to create popout window: {err}");
NewWindowResponse::Deny
}
}
})
.build()?;

app.state::<State>()
.window
.write()
Expand Down
9 changes: 1 addition & 8 deletions src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,7 @@
"plugins": {},
"app": {
"withGlobalTauri": true,
"windows": [
{
"title": "LiveSplit One",
"width": 850,
"height": 750,
"useHttpsScheme": true
}
],
"windows": [],
"security": {
"csp": null
}
Expand Down
2 changes: 2 additions & 0 deletions src/localization/chinese-simplified.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ export function resolveChineseSimplified(text: Label): string {
return "游戏时间";
case Label.PopOut:
return "弹出窗口";
case Label.PopOutFailed:
return "无法打开新窗口。";
case Label.About:
return "关于";
case Label.Back:
Expand Down
2 changes: 2 additions & 0 deletions src/localization/dutch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ export function resolveDutch(text: Label): string {
return "Speltijd";
case Label.PopOut:
return "Pop‑out";
case Label.PopOutFailed:
return "Kan geen nieuw venster openen.";
case Label.About:
return "Over";
case Label.Back:
Expand Down
2 changes: 2 additions & 0 deletions src/localization/english.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ export function resolveEnglish(text: Label): string {
return "Game Time";
case Label.PopOut:
return "Pop Out";
case Label.PopOutFailed:
return "Failed to open a new window.";
case Label.About:
return "About";
case Label.Back:
Expand Down
2 changes: 2 additions & 0 deletions src/localization/french.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ export function resolveFrench(text: Label): string {
return "Temps de jeu";
case Label.PopOut:
return "Fenêtre détachée";
case Label.PopOutFailed:
return "Impossible d’ouvrir une nouvelle fenêtre.";
case Label.About:
return "À propos";
case Label.Back:
Expand Down
2 changes: 2 additions & 0 deletions src/localization/german.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ export function resolveGerman(text: Label): string {
return "Spielzeit";
case Label.PopOut:
return "Pop‑out";
case Label.PopOutFailed:
return "Neues Fenster konnte nicht geöffnet werden.";
case Label.About:
return "Über";
case Label.Back:
Expand Down
1 change: 1 addition & 0 deletions src/localization/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export enum Label {
RealTime,
GameTime,
PopOut,
PopOutFailed,
About,
Back,
AboutVersionPrefix,
Expand Down
2 changes: 2 additions & 0 deletions src/localization/italian.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ export function resolveItalian(text: Label): string {
return "Tempo di gioco";
case Label.PopOut:
return "Finestra separata";
case Label.PopOutFailed:
return "Impossibile aprire una nuova finestra.";
case Label.About:
return "Informazioni";
case Label.Back:
Expand Down
2 changes: 2 additions & 0 deletions src/localization/japanese.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ export function resolveJapanese(text: Label): string {
return "ゲーム時間";
case Label.PopOut:
return "ポップアウト";
case Label.PopOutFailed:
return "新しいウィンドウを開けませんでした。";
case Label.About:
return "このアプリについて";
case Label.Back:
Expand Down
2 changes: 2 additions & 0 deletions src/localization/korean.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ export function resolveKorean(text: Label): string {
return "게임 시간";
case Label.PopOut:
return "팝아웃";
case Label.PopOutFailed:
return "새 창을 열지 못했습니다.";
case Label.About:
return "정보";
case Label.Back:
Expand Down
2 changes: 2 additions & 0 deletions src/localization/polish.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ export function resolvePolish(text: Label): string {
return "Czas gry";
case Label.PopOut:
return "Otwórz w oknie";
case Label.PopOutFailed:
return "Nie udało się otworzyć nowego okna.";
case Label.About:
return "O programie";
case Label.Back:
Expand Down
2 changes: 2 additions & 0 deletions src/localization/portuguese-brazil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ export function resolveBrazilianPortuguese(text: Label): string {
return "Tempo de jogo";
case Label.PopOut:
return "Pop‑out";
case Label.PopOutFailed:
return "Não foi possível abrir uma nova janela.";
case Label.About:
return "Sobre";
case Label.Back:
Expand Down
2 changes: 2 additions & 0 deletions src/localization/portuguese.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ export function resolvePortuguese(text: Label): string {
return "Tempo de jogo";
case Label.PopOut:
return "Pop‑out";
case Label.PopOutFailed:
return "Não foi possível abrir uma nova janela.";
case Label.About:
return "Sobre";
case Label.Back:
Expand Down
2 changes: 2 additions & 0 deletions src/localization/russian.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ export function resolveRussian(text: Label): string {
return "Игровое время";
case Label.PopOut:
return "Окно отдельно";
case Label.PopOutFailed:
return "Не удалось открыть новое окно.";
case Label.About:
return "О программе";
case Label.Back:
Expand Down
2 changes: 2 additions & 0 deletions src/localization/spanish.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ export function resolveSpanish(text: Label): string {
return "Tiempo de juego";
case Label.PopOut:
return "Ventana emergente";
case Label.PopOutFailed:
return "No se pudo abrir una nueva ventana.";
case Label.About:
return "Acerca de";
case Label.Back:
Expand Down
14 changes: 8 additions & 6 deletions src/ui/LiveSplit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1290,12 +1290,11 @@ async function openPopupWindow(
// It's fine if it fails, as not all browsers support this.
}

const childWindow = window.open(
"",
"_blank",
`popup,width=${width},height=${height}`,
);
return childWindow;
try {
return window.open("about:blank", "_blank");
} catch {
return null;
}
}

async function popOut(
Expand All @@ -1307,6 +1306,9 @@ async function popOut(
) {
const childWindow = await openPopupWindow(width, height);
if (!childWindow) {
toast.error(
`${resolve(Label.PopOut, generalSettings.lang)}: ${resolve(Label.PopOutFailed, generalSettings.lang)}`,
);
return;
}

Expand Down