Skip to content

Commit

Permalink
Merge pull request #36 from riskycase/autostart
Browse files Browse the repository at this point in the history
Add autostart support
  • Loading branch information
riskycase authored May 22, 2023
2 parents 762f9ee + a14f771 commit e8a47f1
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 10 deletions.
32 changes: 32 additions & 0 deletions src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ chrono = "0.4.23"
reqwest = { version = "0.11.13", features = ["blocking"] }
regex = "1.7.1"
tl = "0.7.7"
auto-launch = "0.4.0"

[features]
# by default Tauri runs in production mode
Expand Down
84 changes: 84 additions & 0 deletions src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
windows_subsystem = "windows"
)]

use auto_launch::{AutoLaunch, AutoLaunchBuilder, Error};
use regex::Regex;
use serde::{Deserialize, Serialize};
use std::env::current_exe;
use std::io::Write;
use std::sync::{Arc, Mutex};
use tauri::{
Expand Down Expand Up @@ -61,6 +63,22 @@ struct AppState {
last_notification_state: NotificationState,
}

pub struct AutoLaunchManager(AutoLaunch);

impl AutoLaunchManager {
pub fn enable(&self) -> Result<(), Error> {
self.0.enable()
}

pub fn disable(&self) -> Result<(), Error> {
self.0.disable()
}

pub fn is_enabled(&self) -> Result<bool, Error> {
self.0.is_enabled()
}
}

fn save_creds(creds: Credentials, save_file: &std::path::Path) {
let mut file = std::fs::File::create(&save_file).unwrap();
write!(&mut file, "{}", serde_json::to_string(&creds).unwrap()).unwrap();
Expand Down Expand Up @@ -520,6 +538,16 @@ fn credential_check(
}
}

fn auto_launch_check(app: tauri::AppHandle) {
let window: tauri::Window = app.get_window("main").unwrap();
window
.emit(
"autolaunch",
app.state::<AutoLaunchManager>().is_enabled().unwrap(),
)
.unwrap();
}

fn main() {
let tray_menu = tauri::SystemTrayMenu::new()
.add_item(tauri::CustomMenuItem::new("show", "Show window"))
Expand Down Expand Up @@ -590,6 +618,58 @@ fn main() {
.hide()
.unwrap();
});
let mut auto_launch_builder = AutoLaunchBuilder::new();
auto_launch_builder.set_app_name(&app.package_info().name);
let currnet_exe = current_exe();
#[cfg(windows)]
auto_launch_builder.set_app_path(&currnet_exe.unwrap().display().to_string());
#[cfg(target_os = "macos")]
{
// on macOS, current_exe gives path to /Applications/Example.app/MacOS/Example
// but this results in seeing a Unix Executable in macOS login items
// It must be: /Applications/Example.app
// If it didn't find exactly a single occurance of .app, it will default to
// exe path to not break it.
let exe_path = currnet_exe.unwrap().canonicalize()?.display().to_string();
let parts: Vec<&str> = exe_path.split(".app/").collect();
let app_path = if parts.len() == 2 {
format!("{}.app", parts.get(0).unwrap().to_string())
} else {
exe_path
};
auto_launch_builder.set_app_path(&app_path);
}
#[cfg(target_os = "linux")]
if let Some(appimage) = app
.env()
.appimage
.and_then(|p| p.to_str().map(|s| s.to_string()))
{
auto_launch_builder.set_app_path(&appimage);
} else {
auto_launch_builder.set_app_path(&currnet_exe.unwrap().display().to_string());
}

app.manage(AutoLaunchManager(
auto_launch_builder.build().map_err(|e| e.to_string())?,
));

let app_handle_launch = app.app_handle();
app.listen_global("autolaunch", move |event: tauri::Event| {
if event.payload().unwrap().parse::<bool>().unwrap() {
app_handle_launch
.state::<AutoLaunchManager>()
.enable()
.unwrap();
} else {
app_handle_launch
.state::<AutoLaunchManager>()
.disable()
.unwrap();
}
auto_launch_check(app_handle_launch.app_handle());
});

std::fs::create_dir_all(app.path_resolver().app_config_dir().unwrap()).unwrap();
let app_state: State<Arc<Mutex<AppState>>> = app.state::<Arc<Mutex<AppState>>>();
if creds.is_ok() {
Expand All @@ -602,6 +682,7 @@ fn main() {
get_remaining_data(app.app_handle(), true);
} else {
app.get_window("main").unwrap().show().unwrap();
auto_launch_check(app.app_handle());
}
Ok(())
})
Expand All @@ -613,6 +694,7 @@ fn main() {
}
"show" => {
let app_state = app.state::<Arc<Mutex<AppState>>>();
auto_launch_check(app.app_handle());
let window: tauri::Window = app.get_window("main").unwrap();
window
.emit("credentials", app_state.lock().unwrap().credentials.clone())
Expand Down Expand Up @@ -709,6 +791,7 @@ fn main() {
used: "".to_string(),
remaining: "".to_string(),
};
auto_launch_check(app.app_handle());
let window: tauri::Window = app.get_window("main").unwrap();
window
.emit("credentials", app_state.lock().unwrap().credentials.clone())
Expand All @@ -733,6 +816,7 @@ fn main() {
..
} => {
let app_state = app.state::<Arc<Mutex<AppState>>>();
auto_launch_check(app.app_handle());
let window: tauri::Window = app.get_window("main").unwrap();
window
.emit("credentials", app_state.lock().unwrap().credentials.clone())
Expand Down
11 changes: 5 additions & 6 deletions src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,9 @@ export function App() {
used: "",
remaining: "",
});

const [capsLock, setCapsLock] = useState(false);
const [logo, setLogo] = useState(initLogo);
const [BG, setBG] = useState(initBG);
const [autolaunch, setAutolaunch] = useState(false);

useEffect(() => {
listen("credentials", (creds: Event<Credentials>) => {
Expand All @@ -49,16 +48,16 @@ export function App() {
listen("traffic_units", (traffic_units: Event<TrafficUnits>) => {
setTrafficUnits(traffic_units.payload);
});
listen("autolaunch", (enabled: Event<boolean>) => {
setAutolaunch(enabled.payload);
});
document.documentElement.style.setProperty(
"background-image",
`url(${BG})`
);
document.addEventListener("visibilitychange", () => {
if (document.visibilityState === "hidden") emit("minimise");
});
window.addEventListener("keyup", (event) =>
setCapsLock(event.getModifierState("CapsLock"))
);
}, []);

return (
Expand All @@ -74,9 +73,9 @@ export function App() {
<div class={styles.mainContainer}>
<Login
credentials={credentials}
capsLock={capsLock}
setCredentials={setCredentials}
logo={logo}
autolaunch={autolaunch}
/>
<DataBalance
credentials={credentials}
Expand Down
11 changes: 11 additions & 0 deletions src/components/login/login.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@
margin: 0.5rem 0;
}

.autolaunchContainer {
align-self: flex-start;
display: flex;
align-items: center;
font-family: 'Times New Roman', Times, serif;
}

.autolaunchSwitch {
margin: 0 0.5rem;
}

.bitsLogo {
margin: 1rem 0;
height: 6.5rem;
Expand Down
30 changes: 26 additions & 4 deletions src/components/login/login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ import {
InputField,
showToast,
Tag,
Typography,
Toggle,
} from "@cred/neopop-web/lib/components";
import { StateUpdater, useEffect, useState } from "preact/hooks";
import { fetch, Body } from "@tauri-apps/api/http";
import { emit } from "@tauri-apps/api/event";

import styles from "./login.module.scss";
Expand All @@ -19,23 +18,29 @@ export function Login(props: {
username: string;
password: string;
};
capsLock: boolean;
setCredentials: StateUpdater<{
username: string;
password: string;
}>;
logo: string;
autolaunch: boolean;
}) {
const [localUsername, setLocalUsername] = useState(
props.credentials.username
);
const [localPassword, setLocalPassword] = useState(
props.credentials.password
);
const [capsLock, setCapsLock] = useState(false);
useEffect(() => {
setLocalUsername(props.credentials.username);
setLocalPassword(props.credentials.password);
}, [props.credentials]);
useEffect(() => {
window.addEventListener("keyup", (event) =>
setCapsLock(event.getModifierState("CapsLock"))
);
}, []);
return (
<div>
<div class={styles.loginContainer}>
Expand Down Expand Up @@ -77,7 +82,7 @@ export function Login(props: {
margin: "0.5rem 0",
}}
/>
{props.capsLock && (
{capsLock && (
<Tag
colorConfig={{
background: "#010B14",
Expand All @@ -87,6 +92,23 @@ export function Login(props: {
CapsLock is On!
</Tag>
)}
<div class={styles.autolaunchContainer}>
<span class={styles.autolaunchSwitch}>
<Toggle
isChecked={props.autolaunch}
colorMode={"light"}
onChange={(
event: ChangeEvent<HTMLInputElement>
) => {
emit(
"autolaunch",
(event.target as HTMLInputElement).checked
);
}}
/>
</span>
<span>Start at boot</span>
</div>
<Button
variant="primary"
kind="elevated"
Expand Down

0 comments on commit e8a47f1

Please sign in to comment.