mirror of
https://github.com/System-End/hackatime-desktop.git
synced 2026-04-19 22:05:10 +00:00
Compare commits
3 commits
app-v1.7.4
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
832a610693 | ||
|
|
472867d58f | ||
|
|
d037bdb529 |
8 changed files with 92 additions and 32 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
{
|
{
|
||||||
"app": "0.0.0",
|
"app": "0.0.0",
|
||||||
".": "1.7.4"
|
".": "1.7.5"
|
||||||
}
|
}
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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": {
|
||||||
|
|
|
||||||
|
|
@ -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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue