Compare commits

...

3 commits

Author SHA1 Message Date
leafdbot[bot]
832a610693
chore(main): release app 1.7.5 (#67)
Co-authored-by: leafdbot[bot] <192038741+leafdbot[bot]@users.noreply.github.com>
2025-10-24 15:57:29 -06:00
Leafd
472867d58f
fix: eliminate duplicate discord definitions 2025-10-24 17:56:07 -04:00
Leafd
d037bdb529
fix: make option enabled by default 2025-10-24 17:53:30 -04:00
8 changed files with 92 additions and 32 deletions

View file

@ -1,4 +1,4 @@
{ {
"app": "0.0.0", "app": "0.0.0",
".": "1.7.4" ".": "1.7.5"
} }

View file

@ -1,5 +1,13 @@
# Changelog # Changelog
## [1.7.5](https://github.com/hackclub/hackatime-desktop/compare/app-v1.7.4...app-v1.7.5) (2025-10-24)
### 🐛 Bugfixes
* eliminate duplicate discord definitions ([472867d](https://github.com/hackclub/hackatime-desktop/commit/472867d58f306d70241b07b5f3135c34055ad555))
* make option enabled by default ([d037bdb](https://github.com/hackclub/hackatime-desktop/commit/d037bdb529a4a078a5d10f7daa68698da9726e5f))
## [1.7.4](https://github.com/hackclub/hackatime-desktop/compare/app-v1.7.3...app-v1.7.4) (2025-10-24) ## [1.7.4](https://github.com/hackclub/hackatime-desktop/compare/app-v1.7.3...app-v1.7.4) (2025-10-24)

View file

@ -1,7 +1,7 @@
{ {
"name": "desktop", "name": "desktop",
"private": true, "private": true,
"version": "1.7.4", "version": "1.7.5",
"type": "module", "type": "module",
"packageManager": "pnpm@10.18.0", "packageManager": "pnpm@10.18.0",
"scripts": { "scripts": {

View file

@ -283,26 +283,3 @@ pub async fn discord_rpc_auto_disconnect(
rpc_service.disconnect() rpc_service.disconnect()
} }
#[tauri::command]
pub async fn get_discord_rpc_enabled(
discord_rpc_state: State<'_, Arc<tauri::async_runtime::Mutex<DiscordRpcService>>>,
) -> Result<bool, String> {
let rpc_service = discord_rpc_state.lock().await;
Ok(rpc_service.is_connected())
}
#[tauri::command]
pub async fn set_discord_rpc_enabled(
enabled: bool,
discord_rpc_state: State<'_, Arc<tauri::async_runtime::Mutex<DiscordRpcService>>>,
) -> Result<(), String> {
let mut rpc_service = discord_rpc_state.lock().await;
if enabled {
let default_client_id = "1234567890123456789";
rpc_service.connect(default_client_id)
} else {
rpc_service.disconnect()
}
}

View file

@ -140,6 +140,10 @@ pub fn run() {
preferences::get_preferences, preferences::get_preferences,
preferences::set_autostart_enabled, preferences::set_autostart_enabled,
preferences::get_autostart_enabled, preferences::get_autostart_enabled,
preferences::set_notifications_enabled,
preferences::get_notifications_enabled,
preferences::set_discord_rpc_enabled,
preferences::get_discord_rpc_enabled,
setup::setup_hackatime_macos_linux, setup::setup_hackatime_macos_linux,
setup::setup_hackatime_windows, setup::setup_hackatime_windows,
@ -166,8 +170,6 @@ pub fn run() {
discord_rpc::discord_rpc_update_from_heartbeat, discord_rpc::discord_rpc_update_from_heartbeat,
discord_rpc::discord_rpc_auto_connect, discord_rpc::discord_rpc_auto_connect,
discord_rpc::discord_rpc_auto_disconnect, discord_rpc::discord_rpc_auto_disconnect,
discord_rpc::get_discord_rpc_enabled,
discord_rpc::set_discord_rpc_enabled,
projects::get_projects, projects::get_projects,
projects::get_project_details, projects::get_project_details,

View file

@ -9,12 +9,16 @@ use crate::push_log;
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Preferences { pub struct Preferences {
pub autostart_enabled: bool, pub autostart_enabled: bool,
pub notifications_enabled: bool,
pub discord_rpc_enabled: bool,
} }
impl Default for Preferences { impl Default for Preferences {
fn default() -> Self { fn default() -> Self {
Self { Self {
autostart_enabled: false, autostart_enabled: true,
notifications_enabled: true,
discord_rpc_enabled: true,
} }
} }
} }
@ -86,3 +90,45 @@ pub fn get_autostart_enabled() -> Result<bool, String> {
Ok(preferences.autostart_enabled) Ok(preferences.autostart_enabled)
} }
#[tauri::command]
pub fn set_notifications_enabled(enabled: bool) -> Result<(), String> {
let mut preferences = load_preferences().unwrap_or_default();
preferences.notifications_enabled = enabled;
save_preferences(&preferences)?;
if enabled {
push_log("info", "backend", "Notifications enabled".to_string());
} else {
push_log("info", "backend", "Notifications disabled".to_string());
}
Ok(())
}
#[tauri::command]
pub fn get_notifications_enabled() -> Result<bool, String> {
let preferences = load_preferences().unwrap_or_default();
Ok(preferences.notifications_enabled)
}
#[tauri::command]
pub fn set_discord_rpc_enabled(enabled: bool) -> Result<(), String> {
let mut preferences = load_preferences().unwrap_or_default();
preferences.discord_rpc_enabled = enabled;
save_preferences(&preferences)?;
if enabled {
push_log("info", "backend", "Discord RPC enabled".to_string());
} else {
push_log("info", "backend", "Discord RPC disabled".to_string());
}
Ok(())
}
#[tauri::command]
pub fn get_discord_rpc_enabled() -> Result<bool, String> {
let preferences = load_preferences().unwrap_or_default();
Ok(preferences.discord_rpc_enabled)
}

View file

@ -1,7 +1,7 @@
{ {
"$schema": "https://schema.tauri.app/config/2", "$schema": "https://schema.tauri.app/config/2",
"productName": "Hackatime Desktop", "productName": "Hackatime Desktop",
"version": "1.7.4", "version": "1.7.5",
"identifier": "com.hackclub.hackatime", "identifier": "com.hackclub.hackatime",
"build": { "build": {
"beforeDevCommand": "pnpm dev", "beforeDevCommand": "pnpm dev",

View file

@ -45,9 +45,9 @@
<h4 class="font-medium text-text-primary mb-1">Notifications</h4> <h4 class="font-medium text-text-primary mb-1">Notifications</h4>
<p class="text-sm text-text-secondary">Show desktop notifications</p> <p class="text-sm text-text-secondary">Show desktop notifications</p>
</div> </div>
<label class="switch"> <label class="switch" :class="{ 'opacity-50 cursor-not-allowed': isLoading }">
<input type="checkbox" checked> <input type="checkbox" :checked="notificationsEnabled" :disabled="isLoading" @change="toggleNotifications">
<span class="slider"></span> <span class="slider" :class="{ 'animate-pulse': isLoading }"></span>
</label> </label>
</div> </div>
</div> </div>
@ -291,6 +291,7 @@ const emit = defineEmits<{
const discordRpcEnabled = ref(false); const discordRpcEnabled = ref(false);
const autostartEnabled = ref(false); const autostartEnabled = ref(false);
const notificationsEnabled = ref(false);
const isLoading = ref(false); const isLoading = ref(false);
const appVersion = ref('...'); const appVersion = ref('...');
const isClearingCache = ref(false); const isClearingCache = ref(false);
@ -565,6 +566,14 @@ async function loadAutostartState() {
} }
} }
async function loadNotificationsState() {
try {
notificationsEnabled.value = await invoke("get_notifications_enabled");
} catch (error) {
console.error("Failed to load notifications state:", error);
}
}
async function toggleAutostart() { async function toggleAutostart() {
if (isLoading.value) return; if (isLoading.value) return;
@ -599,6 +608,23 @@ async function toggleDiscordRpc() {
} }
} }
async function toggleNotifications() {
if (isLoading.value) return;
isLoading.value = true;
try {
const newState = !notificationsEnabled.value;
await invoke("set_notifications_enabled", { enabled: newState });
notificationsEnabled.value = newState;
} catch (error) {
console.error("Failed to toggle notifications:", error);
notificationsEnabled.value = !notificationsEnabled.value;
} finally {
isLoading.value = false;
}
}
function copyApiKey() { function copyApiKey() {
emit('copyApiKey') emit('copyApiKey')
} }
@ -689,6 +715,7 @@ async function downloadAndInstallUpdate() {
onMounted(async () => { onMounted(async () => {
loadDiscordRpcState(); loadDiscordRpcState();
loadAutostartState(); loadAutostartState();
loadNotificationsState();
try { try {
appVersion.value = await getVersion(); appVersion.value = await getVersion();
} catch (error) { } catch (error) {