Skip to content

Commit 8cad4f2

Browse files
committed
Add auto-update toggle in settings, v2.5.3
1 parent 43ccf4d commit 8cad4f2

5 files changed

Lines changed: 136 additions & 21 deletions

File tree

app.js

Lines changed: 70 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1066,7 +1066,8 @@ function NoteForge() {
10661066
const [masterHint, setMasterHint] = useState(null);
10671067
const [pwDialog, setPwDialog] = useState(null); // null | {type,nbId,...}
10681068
const [pwError, setPwError] = useState("");
1069-
const [unlockedNbs, setUnlockedNbs] = useState(new Set()); // notebook IDs unlocked this session
1069+
const [unlockedNbs, setUnlockedNbs] = useState(new Set());
1070+
const [autoUpdate, setAutoUpdate] = useState(true); // loaded from config // notebook IDs unlocked this session
10701071

10711072
const edRef = useRef(null);
10721073
const saveTimer = useRef(null);
@@ -1187,6 +1188,11 @@ function NoteForge() {
11871188
/* ── Load (encryption-aware) ─────────────────────────────── */
11881189
useEffect(() => {
11891190
(async () => {
1191+
// Load config
1192+
if (window.electronAPI?.getConfig) {
1193+
const cfg = await window.electronAPI.getConfig();
1194+
if (cfg.autoUpdate !== undefined) setAutoUpdate(cfg.autoUpdate);
1195+
}
11901196
if (hasElectronCrypto()) {
11911197
const status = await window.electronAPI.checkEncryption();
11921198
setEncEnabled(status.encrypted);
@@ -2005,9 +2011,9 @@ function NoteForge() {
20052011
s: 32
20062012
})), /*#__PURE__*/React.createElement("div", {
20072013
className: "nf-overlay-title"
2008-
}, "Encryption Settings"), /*#__PURE__*/React.createElement("div", {
2014+
}, "Settings"), /*#__PURE__*/React.createElement("div", {
20092015
className: "nf-overlay-sub"
2010-
}, "AES-256-GCM encryption for all your notes."), /*#__PURE__*/React.createElement("div", {
2016+
}, "Encryption, auto-lock, and updates."), /*#__PURE__*/React.createElement("div", {
20112017
style: {
20122018
textAlign: "left",
20132019
fontSize: 13,
@@ -2016,11 +2022,11 @@ function NoteForge() {
20162022
background: "var(--surface-alt)",
20172023
borderRadius: 8
20182024
}
2019-
}, "Status: ", /*#__PURE__*/React.createElement("strong", {
2025+
}, "Encryption: ", /*#__PURE__*/React.createElement("strong", {
20202026
style: {
20212027
color: encEnabled ? "var(--success)" : "var(--text-muted)"
20222028
}
2023-
}, encEnabled ? "Encrypted" : "Not encrypted")), encEnabled && /*#__PURE__*/React.createElement("div", {
2029+
}, encEnabled ? "Enabled (AES-256-GCM)" : "Not enabled")), encEnabled && /*#__PURE__*/React.createElement("div", {
20242030
style: {
20252031
textAlign: "left",
20262032
fontSize: 13,
@@ -2056,7 +2062,65 @@ function NoteForge() {
20562062
fontSize: 11,
20572063
color: "var(--text-muted)"
20582064
}
2059-
}, "of inactivity")), !encEnabled && /*#__PURE__*/React.createElement("button", {
2065+
}, "of inactivity")), /*#__PURE__*/React.createElement("div", {
2066+
style: {
2067+
textAlign: "left",
2068+
fontSize: 13,
2069+
marginBottom: 16,
2070+
padding: "10px 12px",
2071+
background: "var(--surface-alt)",
2072+
borderRadius: 8,
2073+
display: "flex",
2074+
alignItems: "center",
2075+
justifyContent: "space-between"
2076+
}
2077+
}, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", null, "Auto-update"), /*#__PURE__*/React.createElement("div", {
2078+
style: {
2079+
fontSize: 11,
2080+
color: "var(--text-muted)"
2081+
}
2082+
}, "Check GitHub for new versions on launch")), /*#__PURE__*/React.createElement("label", {
2083+
style: {
2084+
position: "relative",
2085+
width: 40,
2086+
height: 22,
2087+
flexShrink: 0,
2088+
cursor: "pointer"
2089+
}
2090+
}, /*#__PURE__*/React.createElement("input", {
2091+
type: "checkbox",
2092+
checked: autoUpdate,
2093+
onChange: async e => {
2094+
const val = e.target.checked;
2095+
setAutoUpdate(val);
2096+
if (window.electronAPI?.setConfig) await window.electronAPI.setConfig("autoUpdate", val);
2097+
},
2098+
style: {
2099+
opacity: 0,
2100+
width: 0,
2101+
height: 0
2102+
}
2103+
}), /*#__PURE__*/React.createElement("span", {
2104+
style: {
2105+
position: "absolute",
2106+
inset: 0,
2107+
borderRadius: 11,
2108+
background: autoUpdate ? "var(--accent)" : "var(--border)",
2109+
transition: "background .2s"
2110+
}
2111+
}, /*#__PURE__*/React.createElement("span", {
2112+
style: {
2113+
position: "absolute",
2114+
top: 2,
2115+
left: autoUpdate ? 20 : 2,
2116+
width: 18,
2117+
height: 18,
2118+
borderRadius: "50%",
2119+
background: "#fff",
2120+
transition: "left .2s",
2121+
boxShadow: "0 1px 3px rgba(0,0,0,.3)"
2122+
}
2123+
})))), !encEnabled && /*#__PURE__*/React.createElement("button", {
20602124
className: "nf-overlay-btn primary",
20612125
onClick: () => setPwDialog({
20622126
type: "enable-enc"

app.jsx

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,8 @@ function NoteForge(){
337337
const [masterHint,setMasterHint]=useState(null);
338338
const [pwDialog,setPwDialog]=useState(null); // null | {type,nbId,...}
339339
const [pwError,setPwError]=useState("");
340-
const [unlockedNbs,setUnlockedNbs]=useState(new Set()); // notebook IDs unlocked this session
340+
const [unlockedNbs,setUnlockedNbs]=useState(new Set());
341+
const [autoUpdate,setAutoUpdate]=useState(true); // loaded from config // notebook IDs unlocked this session
341342

342343
const edRef=useRef(null);
343344
const saveTimer=useRef(null);
@@ -425,6 +426,11 @@ function NoteForge(){
425426
/* ── Load (encryption-aware) ─────────────────────────────── */
426427
useEffect(()=>{
427428
(async()=>{
429+
// Load config
430+
if(window.electronAPI?.getConfig){
431+
const cfg=await window.electronAPI.getConfig();
432+
if(cfg.autoUpdate!==undefined)setAutoUpdate(cfg.autoUpdate);
433+
}
428434
if(hasElectronCrypto()){
429435
const status=await window.electronAPI.checkEncryption();
430436
setEncEnabled(status.encrypted);
@@ -870,10 +876,10 @@ function NoteForge(){
870876
{pwDialog?.type==="enc-settings"&&<div className="nf-overlay" style={tv} onClick={e=>e.stopPropagation()} onMouseDown={e=>e.stopPropagation()}>
871877
<div className="nf-overlay-card">
872878
<div style={{marginBottom:16}}><I n="shield" s={32}/></div>
873-
<div className="nf-overlay-title">Encryption Settings</div>
874-
<div className="nf-overlay-sub">AES-256-GCM encryption for all your notes.</div>
879+
<div className="nf-overlay-title">Settings</div>
880+
<div className="nf-overlay-sub">Encryption, auto-lock, and updates.</div>
875881
<div style={{textAlign:"left",fontSize:13,marginBottom:16,padding:"10px 12px",background:"var(--surface-alt)",borderRadius:8}}>
876-
Status: <strong style={{color:encEnabled?"var(--success)":"var(--text-muted)"}}>{encEnabled?"Encrypted":"Not encrypted"}</strong>
882+
Encryption: <strong style={{color:encEnabled?"var(--success)":"var(--text-muted)"}}>{encEnabled?"Enabled (AES-256-GCM)":"Not enabled"}</strong>
877883
</div>
878884
{encEnabled&&<div style={{textAlign:"left",fontSize:13,marginBottom:16,padding:"10px 12px",background:"var(--surface-alt)",borderRadius:8,display:"flex",alignItems:"center",gap:8}}>
879885
<span>Auto-lock after</span>
@@ -886,6 +892,21 @@ function NoteForge(){
886892
</select>
887893
<span style={{fontSize:11,color:"var(--text-muted)"}}>of inactivity</span>
888894
</div>}
895+
<div style={{textAlign:"left",fontSize:13,marginBottom:16,padding:"10px 12px",background:"var(--surface-alt)",borderRadius:8,display:"flex",alignItems:"center",justifyContent:"space-between"}}>
896+
<div>
897+
<div>Auto-update</div>
898+
<div style={{fontSize:11,color:"var(--text-muted)"}}>Check GitHub for new versions on launch</div>
899+
</div>
900+
<label style={{position:"relative",width:40,height:22,flexShrink:0,cursor:"pointer"}}>
901+
<input type="checkbox" checked={autoUpdate} onChange={async e=>{
902+
const val=e.target.checked;setAutoUpdate(val);
903+
if(window.electronAPI?.setConfig)await window.electronAPI.setConfig("autoUpdate",val);
904+
}} style={{opacity:0,width:0,height:0}}/>
905+
<span style={{position:"absolute",inset:0,borderRadius:11,background:autoUpdate?"var(--accent)":"var(--border)",transition:"background .2s"}}>
906+
<span style={{position:"absolute",top:2,left:autoUpdate?20:2,width:18,height:18,borderRadius:"50%",background:"#fff",transition:"left .2s",boxShadow:"0 1px 3px rgba(0,0,0,.3)"}}/>
907+
</span>
908+
</label>
909+
</div>
889910
{!encEnabled&&<button className="nf-overlay-btn primary" onClick={()=>setPwDialog({type:"enable-enc"})}>Enable Encryption</button>}
890911
{encEnabled&&<>
891912
<button className="nf-overlay-btn primary" onClick={()=>setPwDialog({type:"change-pw"})}>Change Password</button>

main.js

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,7 @@ function createWindow() {
544544
{ label: "Backup Encrypted Data…", click: send("export-backup") },
545545
{ label: "Restore from Backup…", click: send("restore-backup") },
546546
{ type: "separator" },
547-
{ label: "Encryption Settings…", click: send("encryption-settings") },
547+
{ label: "Settings…", click: send("encryption-settings") },
548548
{ label: "Lock App", accelerator: "CmdOrCtrl+L", click: send("lock-app") },
549549
{ type: "separator" },
550550
{ label: "Open Data Folder", click: send("open-data-folder") },
@@ -571,7 +571,7 @@ function createWindow() {
571571
]},
572572
{ label: "Help", submenu: [
573573
{ label: "About NoteForge", click: () => dialog.showMessageBox(mainWindow, {
574-
type: "info", title: "About NoteForge", message: "NoteForge v2.5.2",
574+
type: "info", title: "About NoteForge", message: "NoteForge v2.5.3",
575575
detail: "Encrypted offline note-taking.\nAES-256-GCM · scrypt (N=65536)\nDerived key session · Auto-lock\n\nData: " + userDataPath,
576576
})},
577577
]},
@@ -589,17 +589,39 @@ app.on("activate", () => { if (!mainWindow) createWindow(); });
589589

590590
/* ═══════════════════════════════════════════════════════════════
591591
AUTO-UPDATER — checks GitHub Releases on startup
592-
Only network activity the app makes. Everything else stays offline.
592+
Only network activity the app makes. Can be disabled in settings.
593593
═══════════════════════════════════════════════════════════════ */
594+
const configFile = path.join(userDataPath, "noteforge-config.json");
595+
596+
function loadConfig() {
597+
try {
598+
if (fs.existsSync(configFile)) return JSON.parse(fs.readFileSync(configFile, "utf-8"));
599+
} catch {}
600+
return { autoUpdate: true };
601+
}
602+
function saveConfig(cfg) {
603+
try { fs.writeFileSync(configFile, JSON.stringify(cfg), "utf-8"); } catch {}
604+
}
605+
606+
ipcMain.handle("get-config", async () => loadConfig());
607+
ipcMain.handle("set-config", async (_e, key, value) => {
608+
const cfg = loadConfig();
609+
cfg[key] = value;
610+
saveConfig(cfg);
611+
return cfg;
612+
});
613+
594614
autoUpdater.autoDownload = false;
595615
autoUpdater.autoInstallOnAppQuit = true;
596616

597617
function setupAutoUpdater() {
598-
if (IS_DEV) return; // don't check for updates in dev mode
618+
if (IS_DEV) return;
619+
const cfg = loadConfig();
620+
if (!cfg.autoUpdate) return; // user disabled auto-update
599621

600622
// Check for updates 5 seconds after launch (non-blocking)
601623
setTimeout(() => {
602-
autoUpdater.checkForUpdates().catch(() => {}); // silently fail if offline
624+
autoUpdater.checkForUpdates().catch(() => {});
603625
}, 5000);
604626

605627
autoUpdater.on("update-available", (info) => {
@@ -632,7 +654,7 @@ function setupAutoUpdater() {
632654
});
633655
});
634656

635-
autoUpdater.on("error", () => {}); // silently ignore update errors (offline, etc.)
657+
autoUpdater.on("error", () => {});
636658
}
637659

638660
ipcMain.handle("check-for-updates", async () => {

package.json

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "noteforge",
3-
"version": "2.5.2",
3+
"version": "2.5.3",
44
"description": "Encrypted offline note-taking — a OneNote alternative that keeps your data local and protected.",
55
"main": "main.js",
66
"author": {
@@ -39,11 +39,15 @@
3939
"target": [
4040
{
4141
"target": "nsis",
42-
"arch": ["x64"]
42+
"arch": [
43+
"x64"
44+
]
4345
},
4446
{
4547
"target": "portable",
46-
"arch": ["x64"]
48+
"arch": [
49+
"x64"
50+
]
4751
}
4852
],
4953
"icon": "assets/icon.ico"
@@ -73,8 +77,8 @@
7377
"electron-updater": "^6.3.0"
7478
},
7579
"devDependencies": {
76-
"@babel/cli": "^7.28.0",
77-
"@babel/preset-react": "^7.28.0",
80+
"@babel/cli": "^7.28.6",
81+
"@babel/preset-react": "^7.28.5",
7882
"electron": "^33.0.0",
7983
"electron-builder": "^25.0.0"
8084
}

preload.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ contextBridge.exposeInMainWorld("electronAPI", {
2020
// Backup
2121
exportBackup: () => ipcRenderer.invoke("export-backup"),
2222
restoreBackup: () => ipcRenderer.invoke("restore-backup"),
23+
// Config
24+
getConfig: () => ipcRenderer.invoke("get-config"),
25+
setConfig: (key, value) => ipcRenderer.invoke("set-config", key, value),
26+
checkForUpdates: () => ipcRenderer.invoke("check-for-updates"),
2327
// Export / Print
2428
exportHTML: (title, html) => ipcRenderer.invoke("export-html", title, html),
2529
exportText: (title, text) => ipcRenderer.invoke("export-text", title, text),

0 commit comments

Comments
 (0)