latex-stickies 1.3.2 → 1.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -88,7 +88,7 @@ Use `Ctrl` in place of `Cmd` on Windows and Linux.
88
88
  | | |
89
89
  |---|---|
90
90
  | `Cmd+N` | New note |
91
- | `Cmd+W` | Close note (it reopens next launch) |
91
+ | `Cmd+W` | Close note (it stays closed until you reopen it) |
92
92
  | `Cmd+Shift+Backspace` | Delete note, permanently |
93
93
  | `Cmd+B` / `Cmd+I` / `Cmd+E` | Bold / italic / code |
94
94
  | `Cmd+K` | Link |
@@ -103,8 +103,9 @@ On Windows and Linux the note windows have no menu bar, so the **☰** button
103
103
  in a note's toolbar opens the same menu. Every command is there.
104
104
 
105
105
  The **All Notes** menu lists every note you have. A tick means it is on screen;
106
- click to open a note, or click a ticked one to close it. So a note you closed
107
- is one click away rather than lost until the next launch.
106
+ click to open a note, or click a ticked one to close it. Closing a note is
107
+ remembered, so the desk you left is the desk you come back to -- the app
108
+ reopens what was on screen rather than every note you have ever written.
108
109
 
109
110
  ## Where notes live
110
111
 
package/build/icon.icns CHANGED
Binary file
package/build/icon.png CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "latex-stickies",
3
- "version": "1.3.2",
3
+ "version": "1.3.4",
4
4
  "description": "Sticky notes for your desktop that render LaTeX and Markdown.",
5
5
  "main": "src/main.js",
6
6
  "scripts": {
@@ -19,6 +19,25 @@ const path = require('path');
19
19
 
20
20
  const NAME = 'LaTeX Stickies';
21
21
 
22
+ /**
23
+ * Makes LaunchServices re-read a bundle.
24
+ *
25
+ * It caches an app's name from the first time it sees the path, and npm
26
+ * extracts Electron under a directory macOS indexes -- so it can record
27
+ * "Electron" before this script ever runs, and then keep showing that in the
28
+ * Dock however right the plist is. Renaming alone is not enough.
29
+ */
30
+ function refreshLaunchServices(appPath) {
31
+ try {
32
+ execFileSync(
33
+ '/System/Library/Frameworks/CoreServices.framework/Frameworks'
34
+ + '/LaunchServices.framework/Support/lsregister',
35
+ ['-f', appPath],
36
+ { stdio: 'ignore', timeout: 10000 }
37
+ );
38
+ } catch (_) { /* the name is still right; only the cache is stale */ }
39
+ }
40
+
22
41
  function main() {
23
42
  if (process.platform !== 'darwin') return; // only macOS names apps this way
24
43
 
@@ -42,7 +61,17 @@ function main() {
42
61
  }
43
62
  };
44
63
 
45
- if (read('CFBundleName') === NAME) return; // already done
64
+ if (read('CFBundleName') === NAME) {
65
+ // Already named, so a wrong name in the Dock can only be a stale cache.
66
+ refreshLaunchServices(appPath);
67
+ // Say so rather than exiting in silence. A user reporting "the Dock still
68
+ // says Electron" needs to know whether the rename failed or whether they
69
+ // are looking at an older instance still holding the single-instance lock.
70
+ if (process.env.LATEX_STICKIES_VERBOSE) {
71
+ console.log(`the Electron shell is already named "${NAME}"`);
72
+ }
73
+ return;
74
+ }
46
75
 
47
76
  const backup = fs.readFileSync(plist);
48
77
  try {
@@ -66,6 +95,8 @@ function main() {
66
95
  });
67
96
  execFileSync('codesign', ['--verify', appPath], { stdio: 'ignore' });
68
97
 
98
+ refreshLaunchServices(appPath);
99
+
69
100
  console.log(`named the Electron shell "${NAME}"`);
70
101
  } catch (err) {
71
102
  fs.writeFileSync(plist, backup);
package/src/main.js CHANGED
@@ -128,6 +128,8 @@ function openNote(note) {
128
128
  return existing;
129
129
  }
130
130
 
131
+ store.upsert({ id: note.id, open: true });
132
+
131
133
  const win = new BrowserWindow({
132
134
  ...onScreenBounds(note.bounds),
133
135
  minWidth: 220,
@@ -158,6 +160,11 @@ function openNote(note) {
158
160
  windows.delete(note.id);
159
161
  smokeLog(`windows=${windows.size}`);
160
162
 
163
+ // Closing a note is a decision that should survive a restart. Quitting is
164
+ // not: an app that shuts down closes every window, and treating that as
165
+ // "the user closed them all" would greet them with an empty desk.
166
+ if (!quitting) store.upsert({ id: note.id, open: false });
167
+
161
168
  // macOS apps outlive their windows; the Dock icon is the way back.
162
169
  // Elsewhere there is no way back, so an app with no windows is just an
163
170
  // invisible process -- and the next launch hands off to it and appears to
@@ -205,13 +212,24 @@ function createNote(seed = {}) {
205
212
  return note;
206
213
  }
207
214
 
215
+ /**
216
+ * Opens the notes that were on screen when the app was last used.
217
+ *
218
+ * Not every note: someone with thirty notes and three on screen wants three
219
+ * windows back, and reopening all of them made closing one pointless. A note
220
+ * closed on purpose stays closed until it is opened again from All Notes.
221
+ */
208
222
  function restoreNotes() {
209
223
  const notes = store.all();
210
224
  if (notes.length === 0) {
211
225
  createNote({ body: WELCOME });
212
226
  return;
213
227
  }
214
- notes.forEach(openNote);
228
+
229
+ const open = notes.filter((n) => n.open !== false);
230
+ // Never nothing. A launch that puts no window on screen looks like a failed
231
+ // launch, and on Windows it leaves an invisible process with no way back.
232
+ (open.length ? open : [notes[notes.length - 1]]).forEach(openNote);
215
233
  }
216
234
 
217
235
  const { WELCOME } = require('./welcome');
@@ -442,6 +460,8 @@ app.on('second-instance', surfaceNotes);
442
460
  * quietly overwriting what was changed on disk.
443
461
  */
444
462
  let stopWatchingNotes = null;
463
+ /** Set while the app is shutting down, so closing windows is not a choice. */
464
+ let quitting = false;
445
465
 
446
466
  /**
447
467
  * Everything that must happen before the process goes away.
@@ -452,6 +472,7 @@ let stopWatchingNotes = null;
452
472
  * process -- alive after the last window has gone.
453
473
  */
454
474
  function prepareToExit() {
475
+ quitting = true;
455
476
  if (stopWatchingNotes) {
456
477
  stopWatchingNotes();
457
478
  stopWatchingNotes = null;
package/src/store.js CHANGED
@@ -25,7 +25,7 @@ const INDEX = path.join(DIR, '.stickies.json');
25
25
  /** The old single-file store, migrated from once and then left alone. */
26
26
  const LEGACY = path.join(app.getPath('userData'), 'notes.json');
27
27
 
28
- const DEFAULTS = { color: 'yellow', fontSize: 15, alwaysOnTop: false };
28
+ const DEFAULTS = { color: 'yellow', fontSize: 15, alwaysOnTop: false, open: true };
29
29
 
30
30
  let notes = null; // [{ id, file, body, color, fontSize, alwaysOnTop, bounds }]
31
31
  let timer = null;
@@ -94,6 +94,9 @@ function load() {
94
94
  ...saved,
95
95
  // The file is the source of truth for content; the index only decorates.
96
96
  id: saved.id || file,
97
+ // A file that appeared in the folder from outside has no index entry,
98
+ // and should show itself rather than stay invisible.
99
+ open: saved.open !== false,
97
100
  file,
98
101
  body,
99
102
  };
@@ -183,6 +186,7 @@ function flushIndex() {
183
186
  fontSize: note.fontSize,
184
187
  alwaysOnTop: note.alwaysOnTop,
185
188
  bounds: note.bounds,
189
+ open: note.open !== false,
186
190
  };
187
191
  }
188
192
  writeIndex(meta);