-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Track file access time, new hook based on access time #87
base: master
Are you sure you want to change the base?
Conversation
This field will track the last access time of the file in the stored metadata. It's added as a part of the `File` interface definition, and implemented for `MarkdownPage`, `Canvas`, and `GenericFile`, as well as their JSON representations.
Because `File`, `Taggable`, `Linkbearing`, and `Fieldbearing` don't have any type overlap with `Indexable` itself, direct casting via `as` isn't possible. We introduce user-defined type-guards to get around this. This adds type narrowing guards for the above mentioned four interfaces.
We utilize the `Workspace`'s `file-open` event for this. We register for the event, then update the `$atime` if we already have existing metadata for the file. Because we know that file access is non-mutating, we don't perform a full reload when this happens. We manually set the `$atime` intrinsic and then call `store` on the file object without recursive sub-storers, as we don't need to re-parse the file contents or other fields in this case. This happens for any `TFile` that has a corresponding datastore entry for its `path` and whose metadata has the `FILE_TYPE` in its `$types` array. If the file is a Markdown or Canvas file, we trigger the persister as well. We then trigger an `update` for the new index revision.
Adds a new Hook to the API that returns a list of files, sorted from most recent to least recent access time. The hook is backed by a query for all `@file` metadata objects that have a populated `$atime` intrinsic. If the query returns no results, we fall back to the Obsidian `Workspace`'s `getLastOpenFiles()` function, which returns the last 10 opened file paths without additional any additional information, and we map those paths to their datastore metadata objects. Because Obsidian itself doesn't track access times, we aren't really able to use the fallback list to update our metadata. We just use it to improve the UX around this new hook.
I'm a bit worried about having this data actually be inside of Datacore's index - the index currently is only updated when the underlying file changes, whereas this now introduces updates on every file open potentially which can be much higher cadence. Additionally, I believe if you mutate the file, the access time will be lost since the indexer and FileStats object do not have last access time. As an interim, perhaps we can add the hook where recent file accesses are stored directly via a queue of recent file accesses? We can persist it to local storage as well to make it work across loads. |
I actually have some more changes locally that address the mutation story, but I was starting to feel bad about inundating you with unsolicited PR's with non-trivial scope. That said, it's not a very ergonomic change set, a different data structure might in fact be more appropriate like you're suggesting. So I'll probably evaluate a different approach instead of pushing those changes up. Anecdotally, I haven't seen any issues with index updates triggering on file access, and I've built a few dashboards on top of this. But I do see where there could be potential for problems with updating the revision with every access. So I'll look at that while I'm revisiting this as well. |
This PR adds a new optional intrinsic field
$atime?: DateTime
to theFile
interface, and updates theMarkdownPage
,Canvas
, andGenericFile
implementations to conform.$atime
is also added to the JSON representations for the above 3 classes:Some type narrowing utilities for the
indexable
interfaces were added during this work to assist with satisfying the type checker:We track
$atime
using the Obsidian Workspacefile-open
event:We also add a new hook,
useLastOpenedFiles
, for getting a list of the most recently accessed files via this new metadata: