mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 22:12:21 -04:00
macOS launcher improvements
- do mpv initial run in parallel - improve messages, show dots regularly
This commit is contained in:
parent
eb6c977e08
commit
d2f818fad2
4 changed files with 81 additions and 44 deletions
|
@ -23,47 +23,45 @@ def first_run_setup() -> None:
|
||||||
if not is_mac:
|
if not is_mac:
|
||||||
return
|
return
|
||||||
|
|
||||||
def _dot():
|
# Import anki_audio first and spawn commands
|
||||||
print(".", flush=True, end="")
|
|
||||||
|
|
||||||
_dot()
|
|
||||||
import anki.collection
|
|
||||||
|
|
||||||
_dot()
|
|
||||||
import PyQt6.sip
|
|
||||||
|
|
||||||
_dot()
|
|
||||||
import PyQt6.QtCore
|
|
||||||
|
|
||||||
_dot()
|
|
||||||
import PyQt6.QtGui
|
|
||||||
|
|
||||||
_dot()
|
|
||||||
import PyQt6.QtNetwork
|
|
||||||
|
|
||||||
_dot()
|
|
||||||
import PyQt6.QtQuick
|
|
||||||
|
|
||||||
_dot()
|
|
||||||
import PyQt6.QtWebChannel
|
|
||||||
|
|
||||||
_dot()
|
|
||||||
import PyQt6.QtWebEngineCore
|
|
||||||
|
|
||||||
_dot()
|
|
||||||
import PyQt6.QtWebEngineWidgets
|
|
||||||
|
|
||||||
_dot()
|
|
||||||
import anki_audio
|
import anki_audio
|
||||||
import PyQt6.QtWidgets
|
|
||||||
|
|
||||||
audio_pkg_path = Path(anki_audio.__file__).parent
|
audio_pkg_path = Path(anki_audio.__file__).parent
|
||||||
|
|
||||||
# Invoke mpv and lame
|
# Start mpv and lame commands concurrently
|
||||||
cmd = [Path(""), "--version"]
|
processes = []
|
||||||
for cmd_name in ["mpv", "lame"]:
|
for cmd_name in ["mpv", "lame"]:
|
||||||
_dot()
|
cmd_path = audio_pkg_path / cmd_name
|
||||||
cmd[0] = audio_pkg_path / cmd_name
|
proc = subprocess.Popen(
|
||||||
subprocess.run([str(cmd[0]), str(cmd[1])], check=True, capture_output=True)
|
[str(cmd_path), "--version"],
|
||||||
|
stdout=subprocess.DEVNULL,
|
||||||
|
stderr=subprocess.DEVNULL,
|
||||||
|
)
|
||||||
|
processes.append(proc)
|
||||||
|
|
||||||
print()
|
# Continue with other imports while commands run
|
||||||
|
import concurrent.futures
|
||||||
|
|
||||||
|
import bs4
|
||||||
|
import flask
|
||||||
|
import flask_cors
|
||||||
|
import markdown
|
||||||
|
import PyQt6.QtCore
|
||||||
|
import PyQt6.QtGui
|
||||||
|
import PyQt6.QtNetwork
|
||||||
|
import PyQt6.QtQuick
|
||||||
|
import PyQt6.QtWebChannel
|
||||||
|
import PyQt6.QtWebEngineCore
|
||||||
|
import PyQt6.QtWebEngineWidgets
|
||||||
|
import PyQt6.QtWidgets
|
||||||
|
import PyQt6.sip
|
||||||
|
import requests
|
||||||
|
import waitress
|
||||||
|
|
||||||
|
import anki.collection
|
||||||
|
|
||||||
|
from . import _macos_helper
|
||||||
|
|
||||||
|
# Wait for both commands to complete
|
||||||
|
for proc in processes:
|
||||||
|
proc.wait()
|
||||||
|
|
|
@ -47,8 +47,8 @@ done
|
||||||
codesign -vvv "$APP_LAUNCHER"
|
codesign -vvv "$APP_LAUNCHER"
|
||||||
spctl -a "$APP_LAUNCHER"
|
spctl -a "$APP_LAUNCHER"
|
||||||
|
|
||||||
# Notarize
|
# Notarize and bundle (skip if NODMG is set)
|
||||||
./notarize.sh "$OUTPUT_DIR"
|
if [ -z "$NODMG" ]; then
|
||||||
|
./notarize.sh "$OUTPUT_DIR"
|
||||||
# Bundle
|
./dmg/build.sh "$OUTPUT_DIR"
|
||||||
./dmg/build.sh "$OUTPUT_DIR"
|
fi
|
|
@ -172,6 +172,8 @@ fn run() -> Result<()> {
|
||||||
command.env("UV_PRERELEASE", "allow");
|
command.env("UV_PRERELEASE", "allow");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
println!("\x1B[1mUpdating Anki...\x1B[0m\n");
|
||||||
|
|
||||||
match command.ensure_success() {
|
match command.ensure_success() {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
// Sync succeeded, break out of loop
|
// Sync succeeded, break out of loop
|
||||||
|
|
|
@ -3,6 +3,11 @@
|
||||||
|
|
||||||
use std::os::unix::process::CommandExt;
|
use std::os::unix::process::CommandExt;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
use std::sync::atomic::AtomicBool;
|
||||||
|
use std::sync::atomic::Ordering;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::thread;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
use anki_process::CommandExt as AnkiCommandExt;
|
use anki_process::CommandExt as AnkiCommandExt;
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
|
@ -25,6 +30,9 @@ pub fn launch_anki_detached(anki_bin: &std::path::Path, _config: &crate::Config)
|
||||||
.process_group(0)
|
.process_group(0)
|
||||||
.ensure_spawn()?;
|
.ensure_spawn()?;
|
||||||
std::mem::forget(child);
|
std::mem::forget(child);
|
||||||
|
|
||||||
|
println!("Anki will start shortly.");
|
||||||
|
println!("\x1B[1mYou can close this window.\x1B[0m\n");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +42,10 @@ pub fn ensure_terminal_shown() -> Result<()> {
|
||||||
// If launched from GUI, relaunch in Terminal.app
|
// If launched from GUI, relaunch in Terminal.app
|
||||||
relaunch_in_terminal()?;
|
relaunch_in_terminal()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set terminal title to "Anki Launcher"
|
||||||
|
print!("\x1b]0;Anki Launcher\x07");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,12 +59,37 @@ fn relaunch_in_terminal() -> Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_first_launch(anki_bin: &std::path::Path) -> Result<()> {
|
pub fn handle_first_launch(anki_bin: &std::path::Path) -> Result<()> {
|
||||||
|
use std::io::Write;
|
||||||
|
use std::io::{
|
||||||
|
self,
|
||||||
|
};
|
||||||
|
|
||||||
// Pre-validate by running --version to trigger any Gatekeeper checks
|
// Pre-validate by running --version to trigger any Gatekeeper checks
|
||||||
println!("\n\x1B[1mThis may take a few minutes. Please wait...\x1B[0m");
|
print!("\n\x1B[1mThis may take a few minutes. Please wait\x1B[0m");
|
||||||
|
io::stdout().flush().unwrap();
|
||||||
|
|
||||||
|
// Start progress indicator
|
||||||
|
let running = Arc::new(AtomicBool::new(true));
|
||||||
|
let running_clone = running.clone();
|
||||||
|
let progress_thread = thread::spawn(move || {
|
||||||
|
while running_clone.load(Ordering::Relaxed) {
|
||||||
|
print!(".");
|
||||||
|
io::stdout().flush().unwrap();
|
||||||
|
thread::sleep(Duration::from_secs(1));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let _ = Command::new(anki_bin)
|
let _ = Command::new(anki_bin)
|
||||||
.env("ANKI_FIRST_RUN", "1")
|
.env("ANKI_FIRST_RUN", "1")
|
||||||
.arg("--version")
|
.arg("--version")
|
||||||
|
.stdout(std::process::Stdio::null())
|
||||||
|
.stderr(std::process::Stdio::null())
|
||||||
.ensure_success();
|
.ensure_success();
|
||||||
|
|
||||||
|
// Stop progress indicator
|
||||||
|
running.store(false, Ordering::Relaxed);
|
||||||
|
progress_thread.join().unwrap();
|
||||||
|
println!(); // New line after dots
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue