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/inject cozy client #461

Merged
merged 19 commits into from
Feb 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 26 additions & 24 deletions src/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,37 +142,38 @@ const getUserActionRequired = () => {
return undefined
}

const determineSSL = (ssl, cozyURL) => {
if (typeof ssl !== 'undefined') return ssl

let parsedURL
try {
parsedURL = new URL(cozyURL)
return parsedURL.protocol === 'https:'
} catch (error) {
console.warn(
`cozyURL parameter passed to Cozy-bar is not a valid URL (${
error.message
}). Cozy-bar will rely on window.location to detect SSL.`
)
}

if (window && window.location && window.location.protocol) {
return window.location.protocol === 'https:'
}

console.warn('Cozy-bar cannot detect SSL and will use default value (true)')
return true
}

let exposedAPI = {}

/**
* Initializes the cozy bar
*
* It can be initialized either with a cozyClient instance
* or a { cozyURL, ssl, token } tupple.
*
* @function
* @param {Object} arg
* @param {string} arg.appName - App name to be displayed in the bar
* @param {string} arg.appNamePrefix
* @param {string} arg.lang - Language for the bar
* @param {string} arg.iconPath -
* @param {Object} arg.cozyClient - a cozy client instance
* @param {string} arg.cozyURL - URL or domain of the stack
* @param {boolean} arg.ssl - Tells if we should use a secure
* protocol required if cozyURL does
* not have a protocol
* @param {string} arg.token - Access token for the stack
* @param {boolean} arg.replaceTitleOnMobile
* @param {boolean} arg.isPublic
* @param {Function} arg.onLogout
* @param {Function} arg.onDeleteApp
*/
const init = async ({
appName,
appNamePrefix = getAppNamePrefix(),
appSlug = getAppSlug(),
lang,
iconPath = getDefaultIcon(),
cozyClient,
cozyURL = getDefaultStackURL(),
token = getDefaultToken(),
replaceTitleOnMobile = false,
Expand All @@ -190,11 +191,12 @@ const init = async ({

reduxStore.dispatch(setInfos(appName, appNamePrefix, appSlug))
stack.init({
cozyClient,
cozyURL,
token,
onCreateApp: app => reduxStore.dispatch(receiveApp(app)),
onDeleteApp: app => reduxStore.dispatch(deleteApp(app)),
ssl: determineSSL(ssl, cozyURL)
ssl
})
if (lang) {
reduxStore.dispatch(setLocale(lang))
Expand Down
17 changes: 14 additions & 3 deletions src/lib/icon.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,20 @@ const mimeTypes = {
svg: 'image/svg+xml'
}

/**
edas marked this conversation as resolved.
Show resolved Hide resolved
* Get an icon URL usable in the HTML page from it's stack path
*
* @function
* @private
* @param {function} iconFetcher - takes an icon path on the stack
* and returns a fetch response with the icon
* @param {object} app - app object with a `links.icon` attribute
* @param {boolean} useCache
* @returns {Promise} url string of an icon usable in the HTML page
* may be empty if the `app` object didn't have an icon path
*/
module.exports = async function getIcon(
cozyUrl,
fetchHeaders,
iconFetcher,
app = {},
useCache = true
) {
Expand All @@ -22,7 +33,7 @@ module.exports = async function getIcon(
let icon

try {
const resp = await fetch(`${cozyUrl}${url}`, fetchHeaders)
const resp = await iconFetcher(url)
if (!resp.ok)
throw new Error(`Error while fetching icon ${resp.statusText}: ${url}`)
icon = await resp.blob()
Expand Down
47 changes: 47 additions & 0 deletions src/lib/normalize-url.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@

edas marked this conversation as resolved.
Show resolved Hide resolved
/**
* Gives an URL object from a partial URL
*
* Mobile apps give us full URL with domain and protocol.
* Web apps may also initialize with a full URL
* but they usually don't, and we the use the
* domain given by the stack through a DOM node
* in the HTML page (despite it not being a full URL).
*
* This function normalizes these different cases
* and returns a full URL object.
*
* The `secure` parameter, if given, always has the
* priority over the one from the URL.
* We use a secure protocol by default if we can't decide.
*
* @param {String} cozyURL - full URL or domain of the cozy
* @param {boolean} secure - optional, force the protocol to use ssl (or not)
* @returns {URL}
*/
export default function normalizeURL(cozyURL, secure) {
if (typeof cozyURL === 'undefined') {
throw new Error("Please give the Cozy URL when initializing the cozy-bar")
}

if (cozyURL.match(/:\/\//)) {
// This is a full URL, probably received from a mobile app.
// The secure parameter overrides the protocol.
if (secure !== undefined) {
cozyURL = cozyURL.replace(/^https?:/, secure ? 'https:' : 'http:')
}
} else {
// We only have the domain, not a real URL.
// Let's decide what protocol we should use.
if (secure === undefined) {
if (window && window.location && window.location.protocol) {
secure = (window.location.protocol === 'https:')
} else {
secure = true
}
}
cozyURL = (secure ? 'https://' : 'http://') + cozyURL
}
return new URL(cozyURL)
}

40 changes: 40 additions & 0 deletions src/lib/realtime.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import realtime from 'cozy-realtime'


/**
* Initialize realtime sockets
*
* @private
* @param {object}
* @returns {Promise}
*/
async function initializeRealtime({ getApp, onCreateApp, onDeleteApp, url, token }) {
const realtimeConfig = { token, url }

try {
realtime
.subscribe(realtimeConfig, 'io.cozy.apps')
.onCreate(async app => {
// Fetch directly the app to get attributes `related` as well.
let fullApp
try {
fullApp = await getApp(app.slug)
} catch (error) {
throw new Error(`Cannot fetch app ${app.slug}: ${error.message}`)
}

if (typeof onCreateApp === 'function') {
onCreateApp(fullApp)
}
})
.onDelete(app => {
if (typeof onDeleteApp === 'function') {
onDeleteApp(app)
}
})
} catch (error) {
console.warn(`Cannot initialize realtime in Cozy-bar: ${error.message}`)
}
}

export default initializeRealtime
Loading