Skip to content

Commit

Permalink
check the sketch version
Browse files Browse the repository at this point in the history
  • Loading branch information
mathieudutour committed Jul 3, 2017
1 parent 95f4bf4 commit cb67f0b
Show file tree
Hide file tree
Showing 12 changed files with 142 additions and 26 deletions.
5 changes: 2 additions & 3 deletions app/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"react-stripe-checkout": "2.4.0",
"react-transition-group": "1.2.0",
"react-virtualized": "9.8.0",
"semver": "^5.3.0",
"source-map-support": "^0.4.15",
"stripe": "4.22.0",
"textarea-caret": "^3.0.2",
Expand Down
2 changes: 2 additions & 0 deletions app/src/lib/app-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ export interface IAppState {
readonly imageDiffType: ImageDiffType

readonly isUnlockingKactusFullAccess: boolean

readonly sketchVersion: string | null | undefined
}

export enum PopupType {
Expand Down
9 changes: 8 additions & 1 deletion app/src/lib/dispatcher/app-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ export class AppStore {

private isUnlockingKactusFullAccess: boolean = false

private sketchVersion: string | null | undefined

public constructor(
gitHubUserStore: GitHubUserStore,
cloningRepositoriesStore: CloningRepositoriesStore,
Expand Down Expand Up @@ -495,6 +497,7 @@ export class AppStore {
showAdvancedDiffs: this.showAdvancedDiffs,
imageDiffType: this.imageDiffType,
isUnlockingKactusFullAccess: this.isUnlockingKactusFullAccess,
sketchVersion: this.sketchVersion,
}
}

Expand Down Expand Up @@ -835,10 +838,14 @@ export class AppStore {
public _loadFromSharedProcess(
accounts: ReadonlyArray<Account>,
repositories: ReadonlyArray<Repository>,
initialLoad: boolean
initialLoad: boolean,
sketchVersion?: string | null
) {
this.accounts = accounts
this.repositories = repositories
if (typeof sketchVersion !== 'undefined') {
this.sketchVersion = sketchVersion
}

// doing this that the current user can be found by any of their email addresses
for (const account of accounts) {
Expand Down
15 changes: 9 additions & 6 deletions app/src/lib/dispatcher/dispatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,8 @@ import {
resolveOAuthRequest,
rejectOAuthRequest,
} from '../../lib/oauth'
import {
saveKactusConfig,
shouldShowPremiumUpsell,
openSketch,
} from '../kactus'
import { saveKactusConfig, shouldShowPremiumUpsell } from '../kactus'
import { openSketch, getSketchVersion } from '../sketch'
import { validatedRepositoryPath } from './validated-repository-path'

/**
Expand Down Expand Up @@ -114,7 +111,13 @@ export class Dispatcher {
public async loadInitialState(): Promise<void> {
const users = await this.loadUsers()
const repositories = await this.loadRepositories()
this.appStore._loadFromSharedProcess(users, repositories, true)
const sketchVersion = await getSketchVersion()
this.appStore._loadFromSharedProcess(
users,
repositories,
true,
sketchVersion
)
}

private dispatchToSharedProcess<T>(action: Action): Promise<T> {
Expand Down
16 changes: 1 addition & 15 deletions app/src/lib/kactus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ import { IKactusStatusResult, find } from 'kactus-cli'
import { Repository } from '../models/repository'
import { Account } from '../models/account'
import { getDotComAPIEndpoint } from './api'

const SKETCH_PATH = '/Applications/Sketch.app'
const SKETCHTOOL_PATH =
SKETCH_PATH + '/Contents/Resources/sketchtool/bin/sketchtool'
import { SKETCHTOOL_PATH } from './sketch'

/**
* Retrieve the status for a given repository
Expand Down Expand Up @@ -169,14 +166,3 @@ export function shouldShowPremiumUpsell(

return false
}

export async function openSketch() {
return await new Promise<void>((resolve, reject) => {
exec('open -a sketch', err => {
if (err) {
return reject(err)
}
resolve()
})
})
}
52 changes: 52 additions & 0 deletions app/src/lib/sketch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import * as Path from 'path'
import { execFile, exec } from 'child_process'

const regex = /sketchtool Version ((\d|\.)+) \(\d+\)/
function extractVersion(s: string) {
const match = regex.exec(s)
return match && match[1]
}

export const SKETCH_PATH = '/Applications/Sketch.app'
export const SKETCHTOOL_PATH = Path.join(
SKETCH_PATH,
'/Contents/Resources/sketchtool/bin/sketchtool'
)

export async function openSketch() {
return await new Promise<void>((resolve, reject) => {
exec('open -a sketch', err => {
if (err) {
return reject(err)
}
resolve()
})
})
}

let sketchVersion: string | undefined

export async function getSketchVersion(): Promise<string | null> {
if (sketchVersion) {
return sketchVersion
}
return new Promise<string | null>((resolve, reject) => {
execFile(Path.join(SKETCHTOOL_PATH), ['-v'], (err, stdout) => {
if (err) {
return resolve(null)
}
let version = extractVersion(stdout)
if (!version) {
return resolve(null)
}
const pointNumbers = version.split('.').length
if (pointNumbers === 1) {
version = version + '.0.0'
} else if (pointNumbers === 2) {
version = version + '.0'
}
sketchVersion = version
return resolve(version)
})
})
}
25 changes: 24 additions & 1 deletion app/src/ui/app.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as React from 'react'
import { ipcRenderer } from 'electron'

import * as semver from 'semver'
import { RepositoriesList } from './repositories-list'
import { RepositoryView } from './repository'
import { TitleBar } from './window/title-bar'
Expand Down Expand Up @@ -38,7 +39,7 @@ import { ILaunchStats } from '../lib/stats'
import { Welcome } from './welcome'
import { AppMenuBar } from './app-menu'
import { findItemByAccessKey, itemIsSelectable } from '../models/app-menu'
import { UpdateAvailable } from './updates'
import { UpdateAvailable, SketchVersionOutdated } from './updates'
import { Preferences } from './preferences'
import { Account } from '../models/account'
import { TipState } from '../models/tip'
Expand Down Expand Up @@ -1295,6 +1296,27 @@ export class App extends React.Component<IAppProps, IAppState> {
)
}

private renderSketchVersionWarning() {
const { sketchVersion } = this.state
if (typeof sketchVersion === 'undefined') {
return null
}

if (sketchVersion === null) {
return (
<SketchVersionOutdated dispatcher={this.props.dispatcher} />
)
}

if (semver.satisfies(sketchVersion, '>=43.0.0')) {
return null
}

return (
<SketchVersionOutdated found={sketchVersion} dispatcher={this.props.dispatcher} />
)
}

private renderToolbar() {
return (
<Toolbar id="desktop-app-toolbar">
Expand Down Expand Up @@ -1386,6 +1408,7 @@ export class App extends React.Component<IAppProps, IAppState> {
? this.renderWelcomeFlow()
: this.renderApp()}
{this.renderZoomInfo()}
{this.renderSketchVersionWarning()}
</div>
)
}
Expand Down
1 change: 1 addition & 0 deletions app/src/ui/updates/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { UpdateAvailable } from './update-available'
export { SketchVersionOutdated } from './sketch-version-outdated'
35 changes: 35 additions & 0 deletions app/src/ui/updates/sketch-version-outdated.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import * as React from 'react'
import { LinkButton } from '../lib/link-button'
import { Octicon, OcticonSymbol } from '../octicons'
import { Dispatcher } from '../../lib/dispatcher'

interface ISketchVersionOutdatedProps {
readonly found?: string
readonly dispatcher: Dispatcher
}

/**
* A component which tells the user an update is available and gives them the
* option of moving into the future or being a luddite.
*/
export class SketchVersionOutdated extends React.Component<
ISketchVersionOutdatedProps,
{}
> {
public render() {
const copy = this.props.found ? `Kactus is only compatible with Sketch >= 43. We found ${this.props.found}.` : 'Kactus needs Sketch to function properly and we couldn\'t find it.'
return (
<div id="update-available" className="active">
<Octicon className="icon" symbol={OcticonSymbol.ruby} />

<span>
{copy} <LinkButton onClick={this.downloadNow}>Download Sketch now</LinkButton>
</span>
</div>
)
}

private downloadNow = () => {
this.props.dispatcher.openInBrowser('https://www.sketchapp.com/updates/')
}
}
6 changes: 6 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@
"@types/react-dom": "15.5.1",
"@types/react-transition-group": "1.1.1",
"@types/react-virtualized": "9.7.2",
"@types/semver": "^5.3.32",
"@types/ua-parser-js": "^0.7.30",
"@types/uuid": "^2.0.29",
"@types/winston": "^2.2.0",
Expand Down

0 comments on commit cb67f0b

Please sign in to comment.