Skip to content
This repository has been archived by the owner on May 7, 2024. It is now read-only.

Commit

Permalink
feat: oauth support (#148)
Browse files Browse the repository at this point in the history
* wip: oauth support

* fix: token fetch

Co-authored-by: Rahul Kadyan <hey@znck.me>
  • Loading branch information
znck and znck committed Jan 19, 2021
1 parent 711342a commit 6a3fcc9
Show file tree
Hide file tree
Showing 22 changed files with 389 additions and 215 deletions.
12 changes: 7 additions & 5 deletions extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -345,13 +345,13 @@
"command": "grammarly.login",
"title": "Login to grammarly.com",
"category": "Grammarly",
"enablement": "grammarly:isAnonymous"
"enablement": "!grammarly:isAuthenticated"
},
{
"command": "grammarly.logout",
"title": "Logout of grammarly.com",
"category": "Grammarly",
"enablement": "!grammarly:isAnonymous"
"enablement": "grammarly:isAuthenticated"
},
{
"command": "grammarly.setGoals",
Expand All @@ -370,14 +370,16 @@
"@types/minimatch": "^3.0.3",
"@types/vscode": "^1.51.0",
"typescript": "^4.0.5",
"unofficial-grammarly-api": "workspace:^0.0.0",
"unofficial-grammarly-language-client": "workspace:^0.0.0",
"unofficial-grammarly-language-server": "workspace:^0.0.0"
"unofficial-grammarly-api": "workspace:*",
"unofficial-grammarly-language-client": "workspace:*",
"unofficial-grammarly-language-server": "workspace:*"
},
"dependencies": {
"@vue/reactivity": "^3.0.2",
"base64url": "^3.0.1",
"inversify": "^5.0.1",
"minimatch": "^3.0.4",
"node-fetch": "^2.6.1",
"reflect-metadata": "^0.1.13"
}
}
36 changes: 14 additions & 22 deletions extension/src/client/index.ts
Original file line number Diff line number Diff line change
@@ -1,43 +1,35 @@
import { GrammarlyLanguageClient } from 'unofficial-grammarly-language-client'
import { ExtensionContext, Uri, workspace } from 'vscode'
import { Disposable, ExtensionContext, Uri, workspace } from 'vscode'
import { AuthenticationService } from '../services/AuthenticationService'
import { Registerable } from '../interfaces'
import { getKeyTar } from '../keytar'

export class GrammarlyClient extends GrammarlyLanguageClient implements Registerable {
constructor(context: ExtensionContext) {
constructor (context: ExtensionContext, private readonly auth: AuthenticationService) {

super(context.asAbsolutePath('dist/server/index.js'), {
info: {
name: 'Grammarly'
},
getCredentials: async () => {
if (process.env.EXTENSION_TEST_MODE) return null

const credentials = (await getKeyTar().findCredentials('vscode-grammarly')) || []

return credentials.length
? {
username: credentials[0].account,
password: credentials[0].password,
}
: null
return null
},
loadToken: async () => {
if (process.env.EXTENSION_TEST_MODE) {
return await getKeyTar().findPassword('vscode-grammarly-cookie')
} else {
return null
}
console.log('Get token...')
if (process.env.EXTENSION_TEST_MODE) return null

return await this.auth.getCookie()
},
saveToken: async (cookie) => {
if (cookie != null) {
getKeyTar().setPassword('vscode-grammarly-cookie', 'default', cookie)
} else {
getKeyTar().deletePassword('vscode-grammarly-cookie', 'default')
}
await this.auth.setCookie(cookie)
},
getIgnoredDocuments: (uri) =>
workspace.getConfiguration('grammarly', Uri.parse(uri)).get<string[]>('ignore') ?? [],
})
}

register() {
return this.grammarly.start()
return Disposable.from(this.start())
}
}
2 changes: 1 addition & 1 deletion extension/src/commands/CheckGrammarCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Registerable } from '../interfaces'

@injectable()
export class CheckCommand implements Registerable {
constructor(private readonly client: GrammarlyClient) {}
constructor (private readonly client: GrammarlyClient) { }

register() {
return Disposable.from(
Expand Down
58 changes: 0 additions & 58 deletions extension/src/commands/SetCredentialsCommand.ts

This file was deleted.

91 changes: 50 additions & 41 deletions extension/src/controllers/StatusBarController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,17 @@ export class StatusBarController implements Registerable {
private state = ref<State | null>(null)
private document = ref<{ uri: string } | null>(null)

constructor(private readonly client: GrammarlyClient) {
constructor (private readonly client: GrammarlyClient) {
this.statusBar.text = '$(globe) Enable Grammarly'
this.statusBar.tooltip = 'Check grammar with Grammarly'
this.statusBar.color = new ThemeColor('statusBar.foreground')
}

register() {
this.client.onReady().then(() => {
this.client.grammarly.onRequest(GrammarlyLanguageServer.Client.Feature.updateDocumentState, (state) => {
this.client.grammarly.onRequest(GrammarlyLanguageServer.Client.Feature.updateDocumentState, async (state) => {
if (this.document.value?.uri === state?.uri) {
this.state.value = state
this.state.value = await this.client.getDocumentState(state.uri)
this.document.value = { uri: state.uri }
}
})
Expand Down Expand Up @@ -56,10 +56,10 @@ export class StatusBarController implements Registerable {
const prefix = state.emotions.length ? state.emotions[0].emoji : ``

this.statusBar.command = 'grammarly.stop'
this.statusBar.text = state.status === 'CHECKING' ? '$(loading~spin)' : '$(globe)'
this.statusBar.tooltip = `${
state.status === 'IDLE' ? 'Grammarly is checking for grammar errors.\n\n' : ''
}Click to disconnect Grammarly.`
this.statusBar.text = `${state.status === 'CHECKING' ? '$(loading~spin)' : '$(debug-disconnect)'} ${state.user.username}`

this.statusBar.tooltip = `${state.status === 'IDLE' ? 'Grammarly is checking for grammar errors.\n\n' : ''
}Click to disconnect Grammarly.`

this.goalsBar.command = 'grammarly.setGoals'
this.goalsBar.text = `${prefix} ${state.score > 0 ? `${state.score} overall score` : ''}`
Expand Down Expand Up @@ -93,24 +93,33 @@ export class StatusBarController implements Registerable {
private getUpgradeTooltip(state: GrammarlyLanguageServer.DocumentState): string {
return state != null && 'status' in state
? formatLines(
(state.totalAlertsCount - state.premiumAlertsCount
? `There are ${state.totalAlertsCount - state.premiumAlertsCount} (of ${
state.totalAlertsCount
}) auto-fixable ${choose(state.totalAlertsCount - state.premiumAlertsCount, 'issue', 'issues')}. `
: '') + this.getUpgradeMessage(state),
35,
)
(state.totalAlertsCount - state.premiumAlertsCount
? `There are ${state.totalAlertsCount - state.premiumAlertsCount} (of ${state.totalAlertsCount
}) auto-fixable ${choose(state.totalAlertsCount - state.premiumAlertsCount, 'issue', 'issues')}. `
: '') + this.getUpgradeMessage(state),
35,
)
: ''
}

private getUpgradeMessage(state: GrammarlyLanguageServer.DocumentState): string {
return state != null && 'status' in state && !state.user.isPremium && state.premiumAlertsCount
? `${state.user.isAnonymous ? 'Login' : 'Upgrade'} to fix ${state.premiumAlertsCount} premium ${choose(
state.premiumAlertsCount,
'issue',
'issues',
)}.${state.user.isAnonymous ? ' Run command - "Grammarly: Login"' : ''}`
: ''
if (state == null || !('status' in state)) return ''
if (state.premiumAlertsCount == 0) return ''
if (state.user.isPremium === true) return ''

if (state.user.isAnonymous) {
return `Login to fix ${state.premiumAlertsCount} premium ${choose(
state.premiumAlertsCount,
'issue',
'issues',
)}. Run command - "Grammarly: Login to grammarly.com"`
} else {
return `Upgrade your Grammarly account to fix ${state.premiumAlertsCount} premium ${choose(
state.premiumAlertsCount,
'issue',
'issues',
)}.`
}
}

private getScoreSummary(state: GrammarlyLanguageServer.DocumentState): string {
Expand All @@ -119,10 +128,10 @@ export class StatusBarController implements Registerable {
`Overall score ${state.score}\n`,
formatLines(
`This score represents the quality of writing in this document. ` +
(state.score < 100
? (state.textInfo?.messages?.assistantHeader ? state.textInfo?.messages?.assistantHeader + '. ' : '') +
`You can increase it by addressing Grammarly's suggestions.`
: ''),
(state.score < 100
? (state.textInfo?.messages?.assistantHeader ? state.textInfo?.messages?.assistantHeader + '. ' : '') +
`You can increase it by addressing Grammarly's suggestions.`
: ''),
35,
),
].join('\n')
Expand All @@ -134,13 +143,13 @@ export class StatusBarController implements Registerable {
private getEmotions(state: GrammarlyLanguageServer.DocumentState) {
return state != null && 'status' in state && state.emotions.length > 0
? [
`\nHere’s how your text sounds:`,
state.emotions.map(
(emotion) => ` ${emotion.emoji} ${capitalize(emotion.name)} ${~~(emotion.confidence * 100)}%`,
),
]
.flat()
.join('\n')
`\nHere’s how your text sounds:`,
state.emotions.map(
(emotion) => ` ${emotion.emoji} ${capitalize(emotion.name)} ${~~(emotion.confidence * 100)}%`,
),
]
.flat()
.join('\n')
: ''
}

Expand All @@ -153,12 +162,12 @@ export class StatusBarController implements Registerable {
private getTextStatesAsMessages(state: GrammarlyLanguageServer.DocumentState): string[] {
return state != null && 'status' in state && state.textInfo != null
? [
`${state.textInfo.wordsCount} ${choose(state.textInfo.wordsCount, 'word', 'words')}`,
`${state.textInfo.charsCount} ${choose(state.textInfo.wordsCount, 'character', 'characters')}`,
`${calculateTime(state.textInfo.wordsCount, 250)} reading time`,
`${calculateTime(state.textInfo.wordsCount, 130)} speaking time`,
`${state.textInfo.readabilityScore} readability score`,
]
`${state.textInfo.wordsCount} ${choose(state.textInfo.wordsCount, 'word', 'words')}`,
`${state.textInfo.charsCount} ${choose(state.textInfo.wordsCount, 'character', 'characters')}`,
`${calculateTime(state.textInfo.wordsCount, 250)} reading time`,
`${calculateTime(state.textInfo.wordsCount, 130)} speaking time`,
`${state.textInfo.readabilityScore} readability score`,
]
: []
}

Expand All @@ -167,9 +176,9 @@ export class StatusBarController implements Registerable {
const scores = Array.from(Object.entries(state.scores))
return scores.length > 0
? [
'\nOutcomes:',
...scores.map(([key, value]) => ` ‣ ${key.replace(/[A-Z]/g, (w) => ' ' + w).trim()}${~~(value! * 100)}`),
].join('\n')
'\nOutcomes:',
...scores.map(([key, value]) => ` ‣ ${key.replace(/[A-Z]/g, (w) => ' ' + w).trim()}${~~(value! * 100)}`),
].join('\n')
: ''
}

Expand Down
9 changes: 5 additions & 4 deletions extension/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { CheckCommand } from './commands/CheckGrammarCommand'
import { ClearCredentialsCommand } from './commands/ClearCredentialsCommand'
import { IgnoreIssueCommand } from './commands/IgnoreIssueCommand'
import { ServerCallbackCommand } from './commands/ServerCallbackCommand'
import { AuthenticationService } from './commands/SetCredentialsCommand'
import { AuthenticationService } from './services/AuthenticationService'
import { SetGoalsCommand } from './commands/SetGoalsCommand'
import { StatsCommand } from './commands/StatsCommand'
import { EXTENSION } from './constants'
Expand All @@ -20,7 +20,8 @@ export async function activate(context: ExtensionContext) {
})

container.bind(EXTENSION).toConstantValue(context)
container.bind(GrammarlyClient).toConstantValue(new GrammarlyClient(context))
container.bind(GrammarlyClient).toConstantValue(new GrammarlyClient(context, container.get(AuthenticationService)))

context.subscriptions.push(
container.get(GrammarlyClient).register(),
container.get(StatusBarController).register(),
Expand All @@ -35,7 +36,7 @@ export async function activate(context: ExtensionContext) {
new Disposable(() => container.unbindAll()),
)

return container.get(GrammarlyClient).onReady()
await container.get(GrammarlyClient).onReady()
}

export function deactivate() {}
export function deactivate() { }
Loading

0 comments on commit 6a3fcc9

Please sign in to comment.