Skip to content
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: popover to configure editor #62452

Merged
merged 20 commits into from May 23, 2024
Merged

feat: popover to configure editor #62452

merged 20 commits into from May 23, 2024

Conversation

bahrmichael
Copy link
Contributor

@bahrmichael bahrmichael commented May 6, 2024

Closes #62292

This PR introduces a new popover to configure the editor.

I had to extend the initial settings to get the current settings, introduce new methods to update settings, and handle the two-step update (because each SettingsEdit can only modify one field). With this solution we get the same look-and-feel like the React app, and the editor icon updates without a page reload.

There's a new updateUserSetting on the root layout, with which this change and other features can update user settings. It fetches the lastID before writing a change, which means it will force the given setting and won't recheck if something changed.

Screen.Recording.2024-05-14.at.13.52.10.mov

Test plan

Manual testing, see video above

@cla-bot cla-bot bot added the cla-signed label May 6, 2024
@bahrmichael
Copy link
Contributor Author

bahrmichael commented May 13, 2024

Update: Since the comment below, I reworked the code to use svelte stores which makes this look nicer. It could still need some improvement, but I'm happier with the code now.


The current setup works, but I'm not very happy with it. The main problem is that editSettings needs the latest settings ID (which comes from the subjects), and can only modify one field at a time.

So to get the lastID when starting out (to make sure that the user's settings haven't been modified in another tab or so), we need to get the lastID that was present when the user open the popover. The lastID changes when we make an edit call, so we have to request it again in between.

I'm hoping there's another way to make this work nicely, but couldn't find one yet. Maybe there's a better Svelte-style approach?

@bahrmichael bahrmichael marked this pull request as ready for review May 14, 2024 12:14
@bahrmichael bahrmichael requested a review from a team May 14, 2024 12:18
Copy link
Contributor

@fkling fkling left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left a couple of comments inline. This might be a tricky one because I assume you just want to get this "done", but at the same time its introducing new behavior (updating user settings) for which it makes sense to have a reasonable API, instead of just doing it "ad hoc". Let me know what you think!

Comment on lines 45 to 46
settings,
subjects,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was hoping we can get away without having to expose individual subjects, but I guess not. However, if we have to expose both then I think we should expose viewerSettings directly (subjects by itself isn't very descriptive). That would require updating all places where we access data.settings of course (of which there seem only two atm).

$: start = position ?? range?.start

$: lastId = writable<number>(subjects.at(-1)?.latestSettings?.id);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know whether we can assume that the last subject is the user one. Looking at the React code, they are extracting the subject with type 'user' which seems safer.

Comment on lines 117 to 139
updateEditor: async (subject: string, lastID: number, edit: SettingsEdit) => {
const mutationResult1 = await client.mutation(
EditSettings,
{
lastID,
subject,
edit,
},
{ requestPolicy: 'network-only', fetch }
)
if (!mutationResult1.data || mutationResult1.error) {
throw new Error(`Failed to update editor path: ${mutationResult1.error}`)
}
const settingsResult = await client.query(LatestSettingsQuery, {})
if (!settingsResult.data || settingsResult.error) {
throw new Error(`Failed to fetch latest settings during editor update: ${settingsResult.error}`)
}
const newLastId = settingsResult.data.viewerSettings.subjects.at(-1)?.latestSettings?.id
if (!newLastId) {
throw new Error('Failed to get new last ID from settings result')
}
return newLastId
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function is called updateEditor but it seems possible to update arbitrary settings with this function.
I'd suggest to create a generic updateSettings function in the root layout data loader.
Looking at the React version it also seems they are retrying the mutation when there was a version error, so the "current" settings ID doesn't seem necessary. Relevant code: https://sourcegraph.sourcegraph.com/github.com/sourcegraph/sourcegraph@cb03009ca0fb1c504f3903bf48e7f5531b6d1cb4/-/blob/client/web/src/platform/context.ts?L51-85

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I can just refresh the IDs it makes things a lot easier! I'll push a new version where I was able to remove a lot of code, and pull the lastID before sending a request.

Comment on lines 50 to 71
$: handleEditorUpdate = async (): Promise<void> => {
if (!$selectedEditorId || !$defaultProjectPath) {
return;
}
isSaving = true;
const newLastId1 = await updateEditor($subjectId, $lastId, {
value: $defaultProjectPath,
keyPath: [{property: 'openInEditor'}, {property: 'projectPaths.default'}],
});
lastId.set(newLastId1);
const newLastId2 = await updateEditor($subjectId, $lastId, {
value: [$selectedEditorId],
keyPath: [{property: 'openInEditor'}, {property: 'editorIds'}],
});
lastId.set(newLastId2);
isSaving = false;

openInEditor = {
editorIds: [$selectedEditorId],
'projectPaths.default': $defaultProjectPath,
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would make sense to abstract some of details of updating settings. E.g. we could provide an API that actually takes an arbitrary number of fields so that the details of the lastId stuff is hidden.
For reference, here is the React version: https://sourcegraph.sourcegraph.com/github.com/sourcegraph/sourcegraph@cb03009ca0fb1c504f3903bf48e7f5531b6d1cb4/-/blob/client/web/src/open-in-editor/OpenInEditorActionItem.tsx?L80-95

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pushed a new version that hides the lastID.

@bahrmichael
Copy link
Contributor Author

I left a couple of comments inline. This might be a tricky one because I assume you just want to get this "done", but at the same time its introducing new behavior (updating user settings) for which it makes sense to have a reasonable API, instead of just doing it "ad hoc". Let me know what you think!

I'm happy to take the hard route. This was my attempt to get something done, so that we can iterate together on making it nice :)

…svelte

Co-authored-by: Felix Kling <felix@felix-kling.de>
Copy link

graphite-app bot commented May 17, 2024

(Notifying @sourcegraph/source of a change that affects gitserver)

@graphite-app graphite-app bot added the team/source Tickets under the purview of Source - the one Source to graph it all label May 17, 2024
@bahrmichael
Copy link
Contributor Author

@fkling I've done another pass, and it looks much cleaner now. The main change was to drop the initial subjects fetch, assuming that we can fetch the lastID before submitting the SettingsEdit.

I'm happy to merge this if you agree.

@bahrmichael bahrmichael requested a review from fkling May 17, 2024 15:52
Copy link
Contributor

@fkling fkling left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, just some nits inside.

@bahrmichael bahrmichael merged commit d8284e3 into main May 23, 2024
8 checks passed
@bahrmichael bahrmichael deleted the bahrmichael/62292 branch May 23, 2024 14:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla-signed team/source Tickets under the purview of Source - the one Source to graph it all
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add config popover to "open in editor" button
2 participants