Skip to content

Commit 9fe3bd0

Browse files
committed
Add direct downloads and first-run support
1 parent 796ad0a commit 9fe3bd0

12 files changed

Lines changed: 231 additions & 15 deletions

File tree

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: Bug report
2+
description: Tell us what went wrong in GazeOff.
3+
title: "[Bug]: "
4+
labels: [bug]
5+
body:
6+
- type: markdown
7+
attributes:
8+
value: Thanks for helping improve GazeOff. Please avoid including private information.
9+
- type: textarea
10+
id: problem
11+
attributes:
12+
label: What happened?
13+
description: Describe the problem and what you expected instead.
14+
validations:
15+
required: true
16+
- type: textarea
17+
id: steps
18+
attributes:
19+
label: Steps to reproduce
20+
placeholder: "1. Open…\n2. Choose…\n3. See…"
21+
validations:
22+
required: true
23+
- type: input
24+
id: version
25+
attributes:
26+
label: GazeOff version
27+
placeholder: "0.1.1"
28+
validations:
29+
required: true
30+
- type: dropdown
31+
id: windows
32+
attributes:
33+
label: Windows version
34+
options:
35+
- Windows 11
36+
- Windows 10
37+
- Other
38+
validations:
39+
required: true
40+
- type: textarea
41+
id: notes
42+
attributes:
43+
label: Anything else?
44+
description: Screenshots and relevant details are welcome.

.github/ISSUE_TEMPLATE/config.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
blank_issues_enabled: false
2+
contact_links:
3+
- name: Private feedback by email
4+
url: mailto:mr.imcommon@gmail.com?subject=GazeOff%20feedback
5+
about: Email the developer when your feedback should not be public.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: Feature request
2+
description: Suggest an improvement or a new GazeOff capability.
3+
title: "[Feature]: "
4+
labels: [enhancement]
5+
body:
6+
- type: textarea
7+
id: need
8+
attributes:
9+
label: What would you like GazeOff to help with?
10+
description: Describe the situation or problem, not only the proposed button or setting.
11+
validations:
12+
required: true
13+
- type: textarea
14+
id: idea
15+
attributes:
16+
label: What would a good solution feel like?
17+
validations:
18+
required: true
19+
- type: textarea
20+
id: alternatives
21+
attributes:
22+
label: Alternatives or examples
23+
description: Share any workarounds or similar features you have seen.

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "gazeoff"
3-
version = "0.1.0"
3+
version = "0.1.1"
44
edition = "2021"
55

66
[build-dependencies]

README.md

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
<p>
1313
<a href="https://gazeoff.vercel.app"><strong>Website</strong></a>
1414
·
15-
<a href="https://github.com/MDSD0/GazeOff/releases/latest"><strong>Download</strong></a>
15+
<a href="https://github.com/MDSD0/GazeOff/releases/latest/download/GazeOff-windows-x64.exe"><strong>Download</strong></a>
1616
·
1717
<a href="docs/FEATURE_CATALOG.md"><strong>Feature catalog</strong></a>
1818
</p>
@@ -91,9 +91,11 @@ These signals are processed on-device. GazeOff has no account system, analytics
9191

9292
## Install
9393

94-
Download the newest Windows build from [GitHub Releases](https://github.com/MDSD0/GazeOff/releases/latest), run `gazeoff.exe`, and find GazeOff in the system tray.
94+
Download the [newest Windows build directly](https://github.com/MDSD0/GazeOff/releases/latest/download/GazeOff-windows-x64.exe), run `GazeOff-windows-x64.exe`, and find GazeOff in the system tray.
9595

96-
> The current release is not signed with a public code-signing certificate. Windows SmartScreen may show a warning on first launch.
96+
> **Windows security note:** GazeOff is not yet code-signed. Windows SmartScreen may offer **More info → Run anyway**. Windows 11 **Smart App Control** is a different protection layer and may block unsigned apps without a per-app bypass. We do not recommend disabling system-wide protection just for GazeOff. See [Microsoft’s Smart App Control guidance](https://support.microsoft.com/en-us/windows/smart-app-control-frequently-asked-questions-285ea03d-fa88-4d56-882e-6698afdb7003).
97+
98+
On the first successful launch, GazeOff opens a welcome window confirming that it is running and showing where to find its tray icon and settings.
9799

98100
## Development
99101

@@ -127,7 +129,7 @@ The release artifact is built with Cargo's optimized release profile. Every GitH
127129
Get-FileHash .\gazeoff.exe -Algorithm SHA256
128130
```
129131

130-
Public code signing is not yet configured, so Windows SmartScreen can ask for confirmation on first launch.
132+
Public code signing is not yet configured. SmartScreen may allow a manual confirmation; Smart App Control may block the unsigned executable entirely.
131133

132134
</details>
133135

@@ -150,6 +152,11 @@ capabilities/ Tauri permission configuration
150152
- [Complete feature catalog](docs/FEATURE_CATALOG.md)
151153
- [Publishing checklist](docs/PUBLISHING_CHECKLIST.md)
152154

155+
## Feedback and support
156+
157+
- [Report a bug or request a feature](https://github.com/MDSD0/GazeOff/issues/new/choose)
158+
- Email [mr.imcommon@gmail.com](mailto:mr.imcommon@gmail.com?subject=GazeOff%20feedback) for private feedback
159+
153160
<div align="center">
154161
<sub>Gaze off. See how beautiful the sky is.</sub>
155162
</div>

src/main.rs

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1576,6 +1576,46 @@ fn settings_window_action(app: AppHandle, action: String) {
15761576
}
15771577
}
15781578

1579+
#[tauri::command]
1580+
fn open_contact(kind: String) -> Result<(), String> {
1581+
let target = match kind.as_str() {
1582+
"issues" => "https://github.com/MDSD0/GazeOff/issues/new/choose",
1583+
"email" => "mailto:mr.imcommon@gmail.com?subject=GazeOff%20feedback",
1584+
_ => return Err("unknown contact destination".into()),
1585+
};
1586+
1587+
#[cfg(windows)]
1588+
let result = std::process::Command::new("rundll32.exe")
1589+
.args(["url.dll,FileProtocolHandler", target])
1590+
.spawn();
1591+
1592+
#[cfg(not(windows))]
1593+
let result = std::process::Command::new("xdg-open").arg(target).spawn();
1594+
1595+
result
1596+
.map(|_| ())
1597+
.map_err(|error| format!("could not open contact destination: {error}"))
1598+
}
1599+
1600+
#[tauri::command]
1601+
fn welcome_action(app: AppHandle, eng: State<Eng>, action: String) {
1602+
match action.as_str() {
1603+
"start" => {
1604+
eng.0.lock().unwrap().paused_until = 0;
1605+
hide(&app, "welcome");
1606+
}
1607+
"settings" => {
1608+
hide(&app, "welcome");
1609+
if let Some(window) = app.get_webview_window("settings") {
1610+
let _ = window.show();
1611+
let _ = window.set_focus();
1612+
}
1613+
}
1614+
"close" => hide(&app, "welcome"),
1615+
_ => {}
1616+
}
1617+
}
1618+
15791619
#[tauri::command]
15801620
fn wallpaper_data_url() -> Option<String> {
15811621
current_wallpaper_data_url()
@@ -1721,6 +1761,8 @@ fn main() {
17211761
toggle_pause,
17221762
open_settings,
17231763
settings_window_action,
1764+
open_contact,
1765+
welcome_action,
17241766
wallpaper_data_url,
17251767
get_recovery_score,
17261768
get_stats,
@@ -1731,6 +1773,7 @@ fn main() {
17311773
])
17321774
.setup(move |app| {
17331775
let handle = app.handle().clone();
1776+
let first_run = !store_path(&handle).exists();
17341777

17351778
// 60fps hardware cursor tracking thread for smooth pre-break texts
17361779
let tracker_handle = handle.clone();
@@ -1763,6 +1806,9 @@ fn main() {
17631806
{
17641807
let mut e = engine.lock().unwrap();
17651808
load(&handle, &mut e);
1809+
if first_run {
1810+
save(&handle, &e);
1811+
}
17661812
if !e.s.start_timer_on_launch {
17671813
e.paused_until = u64::MAX;
17681814
}
@@ -1778,6 +1824,16 @@ fn main() {
17781824
};
17791825

17801826
// windows (all hidden until needed)
1827+
let _welcome =
1828+
WebviewWindowBuilder::new(app, "welcome", WebviewUrl::App("welcome.html".into()))
1829+
.transparent(false)
1830+
.decorations(false)
1831+
.resizable(false)
1832+
.title("Welcome to GazeOff")
1833+
.inner_size(720.0, 540.0)
1834+
.center()
1835+
.visible(first_run)
1836+
.build()?;
17811837
let overlay =
17821838
WebviewWindowBuilder::new(app, "overlay", WebviewUrl::App("overlay.html".into()))
17831839
.transparent(true)
@@ -1863,7 +1919,7 @@ fn main() {
18631919
}
18641920

18651921
// overlay and settings never truly close - they hide
1866-
for label in ["overlay", "settings", "panel", "nudge", "dim", "afk_prompt"] {
1922+
for label in ["welcome", "overlay", "settings", "panel", "nudge", "dim", "afk_prompt"] {
18671923
if let Some(w) = app.get_webview_window(label) {
18681924
let wc = w.clone();
18691925
let is_panel = label == "panel";

tauri.conf.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"$schema": "https://schema.tauri.app/config/2",
33
"productName": "gazeOff",
4-
"version": "0.1.0",
4+
"version": "0.1.1",
55
"identifier": "com.gazeoff.app",
66
"build": {
77
"frontendDist": "ui"

ui/settings.html

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -868,7 +868,22 @@
868868
<div class="group-title">About</div>
869869
<div class="row">
870870
<div class="label">gazeOff<br><span class="hint">A Windows-first eye-care companion.</span></div>
871-
<div class="muted">0.1.0</div>
871+
<div class="muted">0.1.1</div>
872+
</div>
873+
<div class="group-title" style="margin-top: 32px;">Feedback &amp; support</div>
874+
<div class="row">
875+
<div class="label">
876+
Report a bug or request a feature
877+
<div class="hint">Use GitHub Issues so progress and follow-up stay visible.</div>
878+
</div>
879+
<button class="preview-btn" id="contact_issues" type="button">Open GitHub</button>
880+
</div>
881+
<div class="row">
882+
<div class="label">
883+
Email the developer
884+
<div class="hint">For private feedback: mr.imcommon@gmail.com</div>
885+
</div>
886+
<button class="preview-btn" id="contact_email" type="button">Send email</button>
872887
</div>
873888
<div class="row">
874889
<div class="label">
@@ -1111,6 +1126,8 @@
11111126
$('test_debt_nudge').onclick = e => { e.preventDefault(); e.stopPropagation(); invoke('test_nudge', { kind: 'debt' }); };
11121127
$('test_afk_prompt').onclick = e => { e.preventDefault(); e.stopPropagation(); invoke('test_afk_prompt'); };
11131128
$('test_break_overlay').onclick = e => { e.preventDefault(); e.stopPropagation(); invoke('break_now'); };
1129+
$('contact_issues').onclick = () => invoke('open_contact', { kind: 'issues' });
1130+
$('contact_email').onclick = () => invoke('open_contact', { kind: 'email' });
11141131
$('reset_settings').onclick = async e => {
11151132
e.preventDefault();
11161133
e.stopPropagation();

ui/welcome.html

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width,initial-scale=1">
6+
<meta name="color-scheme" content="dark">
7+
<title>Welcome to GazeOff</title>
8+
<style>
9+
:root{color-scheme:dark;--ink:#f7eedb;--soft:rgba(247,238,219,.72);--faint:rgba(247,238,219,.48);--rule:rgba(247,238,219,.16);--accent:#e8a874}
10+
*{box-sizing:border-box}html,body{width:100%;height:100%;margin:0;overflow:hidden}body{position:relative;background:linear-gradient(180deg,#050714 0%,#0a0c1f 28%,#1a1730 58%,#5e3454 100%);color:var(--ink);font-family:Georgia,"Times New Roman",serif;-webkit-font-smoothing:antialiased}
11+
body::before{content:"";position:absolute;inset:0;background:radial-gradient(ellipse at 70% 105%,rgba(232,168,116,.32),transparent 48%);pointer-events:none}
12+
.stars{position:absolute;inset:0;background-image:radial-gradient(circle,#f7eedb 0 1px,transparent 1.2px),radial-gradient(circle,#f7eedb 0 .7px,transparent 1px);background-size:137px 137px,83px 83px;background-position:18px 24px,57px 41px;opacity:.28}
13+
.drag{position:absolute;z-index:3;top:0;left:0;right:54px;height:46px}.close{position:absolute;z-index:4;top:0;right:0;width:54px;height:44px;border:0;background:transparent;color:var(--soft);font:20px sans-serif;cursor:pointer}.close:hover{background:rgba(255,255,255,.08);color:var(--ink)}
14+
main{position:relative;z-index:2;height:100%;padding:58px 64px 48px;display:flex;flex-direction:column}.brand{display:flex;align-items:center;gap:10px;font-size:17px}.mark{width:27px;height:27px;fill:none;stroke:currentColor;stroke-width:1.5}
15+
h1{max-width:560px;margin:46px 0 14px;font-size:54px;line-height:.98;font-weight:400;letter-spacing:-.035em}h1 em{display:block;color:#f2d7b8;font-weight:400}p{margin:0;color:var(--soft);font-size:17px;line-height:1.55}.tray-guide{margin-top:34px;padding:20px 0;display:grid;grid-template-columns:48px 1fr;gap:18px;border-top:1px solid var(--rule);border-bottom:1px solid var(--rule)}.tray-icon{width:42px;height:42px;display:grid;place-items:center;border:1px solid var(--rule);border-radius:8px;background:rgba(5,7,20,.62)}.tray-icon svg{width:25px;height:25px;fill:#f2d7b8}.tray-guide strong{display:block;margin-bottom:4px;font:600 14px system-ui,sans-serif}.tray-guide span{color:var(--faint);font:13px/1.45 system-ui,sans-serif}
16+
.actions{margin-top:auto;display:flex;align-items:center;gap:10px}.actions button{min-height:42px;padding:0 17px;border:1px solid var(--rule);border-radius:7px;background:transparent;color:var(--ink);font:600 13px system-ui,sans-serif;cursor:pointer}.actions .primary{border-color:var(--ink);background:var(--ink);color:#151525}.actions button:hover{border-color:var(--ink)}.actions small{margin-left:auto;color:var(--faint);font:11px system-ui,sans-serif}
17+
</style>
18+
</head>
19+
<body>
20+
<div class="stars" aria-hidden="true"></div>
21+
<div class="drag" data-tauri-drag-region></div>
22+
<button class="close" type="button" aria-label="Close welcome window">×</button>
23+
<main>
24+
<div class="brand"><svg class="mark" viewBox="0 0 32 32" aria-hidden="true"><path d="M4 17c3-6 7-9 12-9s9 3 12 9c-3 5-7 8-12 8S7 22 4 17Z"/><circle cx="16" cy="16.5" r="3.5"/></svg>GazeOff</div>
25+
<h1>You’re all set. <em>Your eyes can exhale.</em></h1>
26+
<p>GazeOff is running quietly in the background and will keep interruptions brief.</p>
27+
<div class="tray-guide">
28+
<div class="tray-icon" aria-hidden="true"><svg viewBox="0 0 32 32"><path d="M5 19c0-4 3-7 7-7 1-4 4-6 8-6 5 0 9 4 9 9 2 1 3 3 3 5 0 4-3 7-7 7H11c-3 0-6-3-6-6v-2Z"/></svg></div>
29+
<div><strong>Look beside the Windows clock</strong><span>Left-click the GazeOff tray icon for your timer. Right-click it for breaks, pause, settings, and quit.</span></div>
30+
</div>
31+
<div class="actions">
32+
<button class="primary" id="start" type="button">Start GazeOff</button>
33+
<button id="settings" type="button">Open settings</button>
34+
<small>GazeOff stays in the tray—not the taskbar.</small>
35+
</div>
36+
</main>
37+
<script>
38+
const invoke=window.__TAURI__.core.invoke;
39+
document.querySelector('#start').onclick=()=>invoke('welcome_action',{action:'start'});
40+
document.querySelector('#settings').onclick=()=>invoke('welcome_action',{action:'settings'});
41+
document.querySelector('.close').onclick=()=>invoke('welcome_action',{action:'close'});
42+
</script>
43+
</body>
44+
</html>

0 commit comments

Comments
 (0)