Problem: Some of us have a few different emails, which show up as
different people when we commit. It would be great to merge these Git
identities so that they don't show up as different people.
Solution: Use `.mailmap`, which lets people choose their favorite
canonical email address for this project.
This allow someone to pass in the theme as a command line arg or set the
theme in defaults.json, while still allowing someone to set the theme on
a per-browser basis as a cookie.
Problem: Our dependencies are falling behind and it'd be nice to have
them up-to-date. The only big update it that Common-Good upgraded to the
latest version of Prettier.
Solution: Update them!
Problem: Trying to view a private message crashes the server and leaks a
bunch of memory. That's bad. This problem is caused by faulty handling
in the function that finds thread ancestors. There's some code that says
"if the next ancestor is a private message, just return the ancestors
that we know about", which returns nothing when we're looking up a
private post (because we can't identify *any* ancestors).
Solution: Ensure that we're only resolving the promise once in the
function by chaining `else if`s and ensure that we only return the
ancestor list if there are actually ancestor in it. If the ancestor list
is empty, we can just return the single message that we know about and
pass it off.
Problem: Since the `errorView()` has a refresh we can probably just call
it `indexingView()` and add the indexing-specific code.
Solution: Rename `errorView()` to `indexingView()` and add a progress
bar for it.
Problem: The indexing message is being thrown as an error, which is
pasted as plaintext, so we can't do a page refresh. This is frustrating
when you're waiting for the indexes to finish because you have to
manually refresh a bunch while you wait.
Solution: Use the prototype from @justinabrahms to add an HTML message
for the indexing error and automatically refresh the page every ten
seconds.
Previously you would get this error due to imperfect path creation
```
node contrib/install-systemd-service.js
fs.js:114
throw err;
^
Error: ENOENT: no such file or directory, copyfile '/home/justin/src/github.com/fraction/oasis/contrib/oasis.service' -> '/home/justin/.config/systemd/user/oasis.service'
at Object.copyFileSync (fs.js:1728:3)
at Object.<anonymous> (/home/justin/src/github.com/fraction/oasis/contrib/install-systemd-service.js:27:6)
at Module._compile (internal/modules/cjs/loader.js:778:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
at Module.load (internal/modules/cjs/loader.js:653:32)
at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
at Function.Module._load (internal/modules/cjs/loader.js:585:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:831:12)
at startup (internal/bootstrap/node.js:283:19)
at bootstrapNodeJSCore (internal/bootstrap/node.js:622:3)
```