Skip to content

Commit

Permalink
Merge pull request #735 from cozy/feat--Flagship-navigation
Browse files Browse the repository at this point in the history
Feat  flagship navigation
  • Loading branch information
acezard authored Feb 11, 2022
2 parents 9763f2a + 0d0bd04 commit 19e08e6
Show file tree
Hide file tree
Showing 17 changed files with 641 additions and 71 deletions.
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
16
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
dist: focal
language: node_js
node_js:
- "10"
- 16
env:
global:
# BUNDLESIZE_GITHUB_TOKEN
Expand Down
9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"babel-preset-cozy-app": "^1.9.0",
"bundlesize": "0.18.0",
"cozy-authentication": "1.19.1",
"cozy-intent": "^1.7.0",
"css-loader": "1.0.1",
"css-mqpacker": "7.0.0",
"cssnano-preset-advanced": "4.0.7",
Expand All @@ -66,6 +67,7 @@
"foreman": "3.0.1",
"identity-obj-proxy": "3.0.0",
"jest": "24.9.0",
"jest-fetch-mock": "^3.0.3",
"json-loader": "0.5.7",
"mini-css-extract-plugin": "0.8.0",
"my-react": "npm:[email protected]",
Expand Down Expand Up @@ -94,8 +96,8 @@
},
"dependencies": {
"@cozy/minilog": "^1.0.0",
"cozy-client": "13.8.3",
"cozy-device-helper": "1.8.0",
"cozy-client": "^27.14.4",
"cozy-device-helper": "^1.16.1",
"cozy-flags": "2.4.1",
"cozy-interapp": "0.4.9",
"cozy-realtime": "3.2.1",
Expand All @@ -112,7 +114,8 @@
"semver-compare": "^1.0.0"
},
"peerDependencies": {
"cozy-client": "*"
"cozy-client": "*",
"cozy-intent": ">=1.7.0"
},
"bundlesize": [
{
Expand Down
14 changes: 4 additions & 10 deletions src/components/Apps/AppNavButtons.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import BottomIcon from 'cozy-ui/react/Icons/Bottom'

import { translate } from 'cozy-ui/react/I18n'
import Icon from 'cozy-ui/react/Icon'
import HomeIcon from 'components/Apps/IconCozyHome'
import { isFetchingApps } from 'lib/reducers'
import { ButtonCozyHome } from './ButtonCozyHome'

class AppNavButton extends Component {
render() {
Expand Down Expand Up @@ -52,16 +52,10 @@ class AppNavButton extends Component {

return (
<div className={`coz-nav-apps-btns${isHomeApp ? ' --currentHome' : ''}`}>
{homeHref ? (
<a href={homeHref} className="coz-nav-apps-btns-home">
<HomeIcon className="coz-nav-apps-btns-home-svg" />
</a>
) : (
<span className="coz-nav-apps-btns-home">
<HomeIcon className="coz-nav-apps-btns-home-svg" />
</span>
)}
<ButtonCozyHome homeHref={homeHref} />

{!isHomeApp && <span className="coz-nav-apps-btns-sep" />}

<button
type="button"
onClick={isPublic ? null : handleClick}
Expand Down
30 changes: 30 additions & 0 deletions src/components/Apps/ButtonCozyHome.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react'

import IconCozyHome from './IconCozyHome'

export const ButtonCozyHome = ({ webviewContext, homeHref }) => {
if (webviewContext)
return (
<button
onClick={() => {
webviewContext.call('backToHome')
}}
className="coz-nav-apps-btns-home --flagship"
>
<IconCozyHome className="coz-nav-apps-btns-home-svg" />
</button>
)

if (homeHref)
return (
<a href={homeHref} className="coz-nav-apps-btns-home">
<IconCozyHome className="coz-nav-apps-btns-home-svg" />
</a>
)

return (
<span className="coz-nav-apps-btns-home">
<IconCozyHome className="coz-nav-apps-btns-home-svg" />
</span>
)
}
53 changes: 53 additions & 0 deletions src/components/Apps/ButtonCozyHome.spec.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React from 'react'
import { shallow } from 'enzyme'

import { ButtonCozyHome } from './ButtonCozyHome'

const homeHref = 'foo'
const expectedCall = 'backToHome'
const webviewContext = {
call: jest.fn()
}

describe('ButtonCozyHome', () => {
it('should render a span with no props', () => {
const render = shallow(<ButtonCozyHome />)
const element = render.getElement()

expect(element.type).toBe('span')
})

it('should render an anchor with correct href when homeHref', () => {
const render = shallow(<ButtonCozyHome homeHref={homeHref} />)
const element = render.getElement()

expect(element.type).toBe('a')
expect(element.props.href).toBe(homeHref)
})

it('should render a button when webviewContext', () => {
const render = shallow(<ButtonCozyHome webviewContext={webviewContext} />)
const element = render.getElement()

expect(element.type).toBe('button')
})

it('should give priority to button if both webviewContext and homeHref are present', () => {
const render = shallow(
<ButtonCozyHome homeHref={homeHref} webviewContext={webviewContext} />
)
const element = render.getElement()

expect(element.type).toBe('button')
})

it('should call the correct context method on click', () => {
const render = shallow(
<ButtonCozyHome homeHref={homeHref} webviewContext={webviewContext} />
)

render.simulate('click')

expect(webviewContext.call).toBeCalledWith(expectedCall)
})
})
15 changes: 12 additions & 3 deletions src/components/Bar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
} from 'cozy-ui/react/helpers/tracker'
import { isMobileApp } from 'cozy-device-helper'

import { ButtonCozyHome } from 'components/Apps/ButtonCozyHome'
import Banner from 'components/Banner'
import Drawer from 'components/Drawer'
import Settings from 'components/Settings'
Expand All @@ -27,7 +28,8 @@ import {
fetchApps,
fetchContext,
fetchSettingsData,
shouldEnableClaudy
shouldEnableClaudy,
getWebviewContext
} from 'lib/reducers'

/* Generated with node_modules/.bin/svgr src/assets/sprites/icon-apps.svg */
Expand Down Expand Up @@ -163,7 +165,12 @@ export class Bar extends Component {
}

renderLeft = () => {
const { t, isPublic } = this.props
const { t, isPublic, webviewContext } = this.props

if (webviewContext) {
return <ButtonCozyHome webviewContext={webviewContext} />
}

// data-tutorial attribute allows to be targeted in an application tutorial
return !isPublic ? (
<button
Expand Down Expand Up @@ -197,6 +204,7 @@ export class Bar extends Component {
supportDisplayed,
usageTracker
} = this.state

const {
theme,
themeOverrides,
Expand Down Expand Up @@ -269,7 +277,8 @@ export const mapStateToProps = state => ({
barSearch: getContent(state, 'search'),
isDrive: isCurrentApp(state, { slug: 'drive' }),
claudyEnabled: shouldEnableClaudy(state),
hasFetchedApps: hasFetched(state)
hasFetchedApps: hasFetched(state),
webviewContext: getWebviewContext(state)
})

export const mapDispatchToProps = dispatch => ({
Expand Down
6 changes: 4 additions & 2 deletions src/components/Bar.spec.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react'
import { shallow } from 'enzyme'
import { isMobileApp } from 'cozy-device-helper'
import { isFlagshipApp, isMobileApp } from 'cozy-device-helper'
import toJson from 'enzyme-to-json'
import reducers from 'lib/reducers'
import CozyClient from 'cozy-client'
Expand All @@ -9,7 +9,8 @@ import { Bar, mapStateToProps, mapDispatchToProps } from './Bar'

jest.mock('cozy-device-helper', () => ({
...require.requireActual('cozy-device-helper'),
isMobileApp: jest.fn()
isMobileApp: jest.fn(),
isFlagshipApp: jest.fn()
}))

describe('Bar', () => {
Expand All @@ -32,6 +33,7 @@ describe('Bar', () => {

afterEach(() => {
Bar.prototype.fetchApps.mockRestore()
isFlagshipApp.mockClear()
})

it('should fetch data when mounted', () => {
Expand Down
1 change: 1 addition & 0 deletions src/components/__snapshots__/Bar.spec.jsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ Object {
"isDrive": false,
"theme": "default",
"themeOverrides": Object {},
"webviewContext": undefined,
}
`;

Expand Down
4 changes: 3 additions & 1 deletion src/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,8 @@ const {
BarRight,
BarLeft,
BarSearch,
setTheme
setTheme,
setWebviewContext
} = proxiedAPI

const version = __VERSION__
Expand All @@ -235,6 +236,7 @@ export {
BarCenter,
BarSearch,
setTheme,
setWebviewContext,
setLocale,
updateAccessToken
}
6 changes: 6 additions & 0 deletions src/index.spec.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import CozyClient from 'cozy-client'
import jestFetchMock from 'jest-fetch-mock'

import * as cozyBar from './index'

describe('init', () => {
beforeAll(() => {
global.fetch = jestFetchMock
})

beforeEach(() => {
jest.spyOn(console, 'error')
const div = document.createElement('div')
Expand Down
14 changes: 12 additions & 2 deletions src/lib/api/index.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import React, { Component } from 'react'
import { setContent, unsetContent, setLocale, setTheme } from 'lib/reducers'
import {
setContent,
unsetContent,
setLocale,
setTheme,
setWebviewContext
} from 'lib/reducers'

import { locations, getJsApiName, getReactApiName } from 'lib/api/helpers'

Expand Down Expand Up @@ -90,6 +96,10 @@ export const createBarAPI = store => {
store.dispatch(setTheme(...args))
}

methods.setWebviewContext = (...args) => {
store.dispatch(setWebviewContext(...args))
}

return methods
}

Expand Down Expand Up @@ -128,7 +138,7 @@ export const createBarProxiedAPI = exposedAPI => {
}
})

for (let fnName of ['setLocale', 'setTheme']) {
for (let fnName of ['setLocale', 'setTheme', 'setWebviewContext']) {
apiReferences[fnName] = makeProxyMethodToAPI(exposedAPI, fnName)
}
return apiReferences
Expand Down
14 changes: 11 additions & 3 deletions src/lib/reducers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { combineReducers } from 'redux'
import * as content from 'lib/reducers/content'
import * as locale from 'lib/reducers/locale'
import * as theme from 'lib/reducers/theme'
import * as unserializable from 'lib/reducers/unserializable'
import appsReducer, * as apps from 'lib/reducers/apps'
import settingsReducer, * as settings from 'lib/reducers/settings'
import contextReducer, * as context from 'lib/reducers/context'
Expand All @@ -16,6 +17,7 @@ const setContent = content.setContent
const unsetContent = content.unsetContent
const setLocale = locale.setLocale
const setTheme = theme.setTheme
const setWebviewContext = unserializable.setWebviewContext
const fetchApps = apps.fetchApps
const setInfos = apps.setInfos
const fetchSettingsData = settings.fetchSettingsData
Expand All @@ -26,6 +28,7 @@ export {
unsetContent,
setLocale,
setTheme,
setWebviewContext,
fetchApps,
setInfos,
fetchSettingsData,
Expand All @@ -48,18 +51,23 @@ export const isFetchingSettings = proxy('settings', settings.isFetchingSettings)
export const getHelpLink = proxy('context', context.getHelpLink)
export const getClaudyActions = proxy('context', context.getClaudyActions)
export const shouldEnableClaudy = proxy('context', context.shouldEnableClaudy)
export const getWebviewContext = proxy(
'unserializable',
unserializable.getWebviewContext
)

// realtime handlers
export const onRealtimeCreate = apps.receiveApp
export const onRealtimeDelete = apps.deleteApp

export const reducers = {
apps: appsReducer,
content: content.reducer,
context: contextReducer,
locale: locale.reducer,
theme: theme.reducer,
apps: appsReducer,
settings: settingsReducer,
context: contextReducer
theme: theme.reducer,
unserializable: unserializable.reducer
}

export default combineReducers(reducers)
26 changes: 26 additions & 0 deletions src/lib/reducers/unserializable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const SET_WEBVIEW_CONTEXT = 'SET_WEBVIEW_CONTEXT'

// selectors
export const getWebviewContext = state => {
return state.webviewContext
}

// actions
export const setWebviewContext = payload => ({
type: SET_WEBVIEW_CONTEXT,
payload
})

// reducers
const defaultState = {
webviewContext: undefined
}

export const reducer = (state = defaultState, action) => {
switch (action.type) {
case SET_WEBVIEW_CONTEXT:
return { ...state, webviewContext: action.payload }
default:
return state
}
}
Loading

0 comments on commit 19e08e6

Please sign in to comment.