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: Handle offline mode in Flagship app #660

Draft
wants to merge 11 commits into
base: master
Choose a base branch
from
3 changes: 2 additions & 1 deletion manifest.webapp
Original file line number Diff line number Diff line change
Expand Up @@ -138,5 +138,6 @@
"max_number_of_files": 1,
"max_size_per_file_in_MB": 10,
"route_to_upload": "/#/paper/create?fromFlagshipUpload=true"
}
},
"offline_support": true
}
12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,13 @@
"@sentry/integrations": "7.88.0",
"@sentry/react": "7.119.0",
"classnames": "2.5.1",
"cozy-bar": "^15.0.0",
"cozy-client": "^48.25.0",
"cozy-device-helper": "^3.0.0",
"cozy-bar": "^15.0.1",
"cozy-client": "^49.0.0",
"cozy-device-helper": "^3.1.0",
"cozy-doctypes": "^1.90.0",
"cozy-flags": "^3.2.2",
"cozy-harvest-lib": "^30.0.0",
"cozy-intent": "^2.21.0",
"cozy-harvest-lib": "^30.0.1",
"cozy-intent": "^2.23.0",
"cozy-interapp": "^0.9.0",
"cozy-keys-lib": "^6.0.0",
"cozy-logger": "^1.10.4",
Expand All @@ -93,7 +93,7 @@
"cozy-realtime": "^5.0.0",
"cozy-sharing": "^16.0.0",
"cozy-ui": "^111.12.0",
"cozy-viewer": "^1.1.2",
"cozy-viewer": "^2.0.0",
"date-fns": "2.23.0",
"flexsearch": "0.7.31",
"leaflet": "1.7.1",
Expand Down
5 changes: 3 additions & 2 deletions src/components/Actions/Items/download.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const download = ({
label,
icon,
disabled: docs => docs.length === 0,
action: async (docs, { client }) => {
action: async (docs, { client, webviewIntent }) => {
const fromMultiSelection = allMultiSelection.length > 0
const normalizedDocs =
allMultiSelection.length > 0
Expand All @@ -48,7 +48,8 @@ export const download = ({
showAlert,
t,
pushModal,
popModal
popModal,
webviewIntent
})
isMultiSelectionActive && navigate('..')
},
Expand Down
16 changes: 12 additions & 4 deletions src/components/Actions/handleFileDownloading.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { is2SidedFile } from 'src/helpers/is2SidedFile'
* @param {Function} params.showAlert - Function to show an alert
* @param {Function} params.t - Translation function
* @param {boolean} [params.fromMultiSelection] - Whether the action is from a multi-selection
* @param {WebviewService | undefined} [params.webviewIntent] - WebviewIntent used to call methods on FlagshipApp (when hosted in a WebView)
*/
export const handleFileDownloading = async ({
client,
Expand All @@ -21,7 +22,8 @@ export const handleFileDownloading = async ({
pushModal,
popModal,
t,
fromMultiSelection
fromMultiSelection,
webviewIntent
}) => {
if (
filesWithPage.length === 1 &&
Expand All @@ -37,18 +39,24 @@ export const handleFileDownloading = async ({
textAction={t('action.download')}
onClick={selectedChoice => {
const selected = onPickSelectedPage(selectedChoice, file)
downloadFiles({ client, t, filesWithPage: selected, showAlert })
downloadFiles({
client,
t,
filesWithPage: selected,
showAlert,
webviewIntent
})
}}
onClose={popModal}
/>
)
} else {
downloadFiles({ client, t, filesWithPage, showAlert })
downloadFiles({ client, t, filesWithPage, showAlert, webviewIntent })
}
return
}

if (filesWithPage.length > 0) {
downloadFiles({ client, t, filesWithPage, showAlert })
downloadFiles({ client, t, filesWithPage, showAlert, webviewIntent })
}
}
13 changes: 4 additions & 9 deletions src/components/Actions/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { handleConflictFilename } from 'src/helpers/handleConflictFilename'

import { isReferencedBy } from 'cozy-client'
import { getDisplayName } from 'cozy-client/dist/models/contact'
import { splitFilename } from 'cozy-client/dist/models/file'
import { downloadFile, splitFilename } from 'cozy-client/dist/models/file'
import { getSharingLink } from 'cozy-client/dist/models/sharing'

export const isAnyFileReferencedBy = (files, doctype) => {
Expand Down Expand Up @@ -200,20 +200,15 @@ export const downloadFiles = async ({
client,
filesWithPage,
showAlert,
t
t,
webviewIntent
}) => {
try {
const fileCollection = client.collection(FILES_DOCTYPE)
if (filesWithPage.length === 1) {
const { file, page } = filesWithPage[0]
if (filesWithPage[0].page === null) {
const filename = file.name
const downloadURL = await fileCollection.getDownloadLinkById(
file.id,
filename
)

return fileCollection.forceFileDownload(`${downloadURL}?Dl=1`, filename)
return await downloadFile({ client, file, webviewIntent })
} else {
const filename = makeFilenameWithPage({ file, page, t })
const bin = await getPdfPage({
Expand Down
73 changes: 35 additions & 38 deletions src/components/AppProviders.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import { launchMetadataMigrationJob } from 'src/helpers/migration/metadata'

import { BarProvider } from 'cozy-bar'
import { CozyProvider } from 'cozy-client'
import { WebviewIntentProvider } from 'cozy-intent'
import AlertProvider from 'cozy-ui/transpiled/react/providers/Alert'
import { BreakpointsProvider } from 'cozy-ui/transpiled/react/providers/Breakpoints'
import CozyTheme from 'cozy-ui/transpiled/react/providers/CozyTheme'
Expand Down Expand Up @@ -45,43 +44,41 @@ export const AppProviders = ({ client, lang, polyglot, children }) => {

return (
<ErrorProvider>
<WebviewIntentProvider>
<StylesProvider generateClassName={generateClassName}>
<CozyProvider client={client}>
<I18n lang={lang} polyglot={polyglot}>
<CozyTheme>
<BreakpointsProvider>
<BarProvider>
<PapersCreatedProvider>
<AlertProvider>
<PaywallProvider>
<ScannerI18nProvider>
<FileSharingProvider>
<SearchProvider
doctypes={[FILES_DOCTYPE, CONTACTS_DOCTYPE]}
>
<PapersDefinitionsProvider>
<ModalProvider>
<CreatePaperDataBackupProvider>
<MultiSelectionProvider>
{children}
</MultiSelectionProvider>
</CreatePaperDataBackupProvider>
</ModalProvider>
</PapersDefinitionsProvider>
</SearchProvider>
</FileSharingProvider>
</ScannerI18nProvider>
</PaywallProvider>
</AlertProvider>
</PapersCreatedProvider>
</BarProvider>
</BreakpointsProvider>
</CozyTheme>
</I18n>
</CozyProvider>
</StylesProvider>
</WebviewIntentProvider>
<StylesProvider generateClassName={generateClassName}>
<CozyProvider client={client}>
<I18n lang={lang} polyglot={polyglot}>
<CozyTheme>
<BreakpointsProvider>
<BarProvider>
<PapersCreatedProvider>
<AlertProvider>
<PaywallProvider>
<ScannerI18nProvider>
<FileSharingProvider>
<SearchProvider
doctypes={[FILES_DOCTYPE, CONTACTS_DOCTYPE]}
>
<PapersDefinitionsProvider>
<ModalProvider>
<CreatePaperDataBackupProvider>
<MultiSelectionProvider>
{children}
</MultiSelectionProvider>
</CreatePaperDataBackupProvider>
</ModalProvider>
</PapersDefinitionsProvider>
</SearchProvider>
</FileSharingProvider>
</ScannerI18nProvider>
</PaywallProvider>
</AlertProvider>
</PapersCreatedProvider>
</BarProvider>
</BreakpointsProvider>
</CozyTheme>
</I18n>
</CozyProvider>
</StylesProvider>
</ErrorProvider>
)
}
33 changes: 31 additions & 2 deletions src/components/AppRouter.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react'
import React, { useEffect, useState } from 'react'
import {
Navigate,
Outlet,
Expand All @@ -24,6 +24,10 @@ import InformationEdit from 'src/components/Views/InformationEdit'
import MultiselectView from 'src/components/Views/MultiselectView'
import ConditionnalPapersList from 'src/components/Views/PapersList'
import PlaceholdersSelector from 'src/components/Views/PlaceholdersSelector'
import { makeClient } from 'src/targets/browser/makeClient'

import { isFlagshipApp } from 'cozy-device-helper'
import { useWebviewIntent, WebviewIntentProvider } from 'cozy-intent'

const fileViewerRoutes = props => [
{
Expand Down Expand Up @@ -165,7 +169,32 @@ const makeRoutes = props => [
]

export const AppRouter = props => {
const router = createHashRouter(makeRoutes(props))
return (
<WebviewIntentProvider>
<AppSubRouter {...props} />
</WebviewIntentProvider>
)
}

export const AppSubRouter = props => {
const webviewIntent = useWebviewIntent()
const [client, setClient] = useState(undefined)

useEffect(() => {
if (isFlagshipApp() && !webviewIntent) return

const client = makeClient(webviewIntent)

setClient(client)
}, [webviewIntent])

if (!client) {
return null
}

const propsWithClient = { ...props, client }

const router = createHashRouter(makeRoutes(propsWithClient))

return <RouterProvider router={router} />
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const ScanDesktopActions = ({ onOpenFilePickerModal, onChangeFile }) => {
const showAlert = flag('mespapiers.aa-suggestion.disabled')
? false
: isLoadedSettings
? settingsData[0].showScanDesktopActionsAlert ?? true
? settingsData[0]?.showScanDesktopActionsAlert ?? true
: true

const handleKeyDown = ({ key }) => {
Expand Down
2 changes: 1 addition & 1 deletion src/doctypes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { QueryDefinition, HasMany } from 'cozy-client'

class HasManyBills extends HasMany {
get data() {
const refs = this.target.relationships.referenced_by.data
const refs = this.target.relationships.referenced_by?.data
return refs
? refs
.map(ref => {
Expand Down
9 changes: 5 additions & 4 deletions src/queries/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,16 +108,17 @@ export const buildFilesQueryByLabel = label => ({
definition: () =>
Q(FILES_DOCTYPE)
.where({
'metadata.qualification': {
label: label
}
created_at: {
$gt: null
},
'metadata.qualification.label': label
})
.partialIndex({
type: 'file',
trashed: false,
'cozyMetadata.createdByApp': { $exists: true }
})
.indexFields(['created_at', 'metadata.qualification'])
.indexFields(['created_at', 'metadata.qualification.label'])
.sortBy([{ created_at: 'desc' }]),
options: {
as: `${FILES_DOCTYPE}/${label}`,
Expand Down
18 changes: 15 additions & 3 deletions src/targets/browser/makeClient.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
import schema from 'src/doctypes'

import CozyClient from 'cozy-client'
import CozyClient, { WebFlagshipLink } from 'cozy-client'
import { isFlagshipApp, isFlagshipOfflineSupported } from 'cozy-device-helper'
import flag from 'cozy-flags'
import { Intents } from 'cozy-interapp'
import { RealtimePlugin } from 'cozy-realtime'

import manifest from '../../../manifest.webapp'

/**
* Make and returns cozy client instance
* @returns {import('cozy-client/types/CozyClient').default} cozy client instance
*/
export const makeClient = () => {
export const makeClient = intent => {
const root = document.querySelector('[role=application]')
const data = JSON.parse(root.dataset.cozy)
const protocol = window.location.protocol
const cozyUrl = `${protocol}//${data.domain}`

const shouldUseWebFlagshipLink =
isFlagshipApp() && isFlagshipOfflineSupported()

const client = new CozyClient({
uri: cozyUrl,
token: data.token,
Expand All @@ -23,11 +29,17 @@ export const makeClient = () => {
version: manifest.version
},
schema,
store: true
store: true,
links: shouldUseWebFlagshipLink
? new WebFlagshipLink({ webviewIntent: intent })
: null
})

const intents = new Intents({ client })
client.intents = intents

client.registerPlugin(RealtimePlugin)
client.registerPlugin(flag.plugin)

return client
}
8 changes: 1 addition & 7 deletions src/targets/browser/setupApp.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import { CaptureConsole } from '@sentry/integrations'
import * as Sentry from '@sentry/react'
import memoize from 'lodash/memoize'
import { makeClient } from 'src/targets/browser/makeClient'

import flag from 'cozy-flags'
import { RealtimePlugin } from 'cozy-realtime'
import { initTranslation } from 'cozy-ui/transpiled/react/providers/I18n'

import manifest from '../../../manifest.webapp'
Expand All @@ -20,9 +17,6 @@ const setupApp = memoize(() => {
const locale = JSON.parse(root.dataset.cozy)?.locale
const lang = getDataOrDefault(locale, 'en')
const polyglot = initTranslation(lang, lang => require(`locales/${lang}`))
const client = makeClient()
client.registerPlugin(RealtimePlugin)
client.registerPlugin(flag.plugin)

Sentry.init({
dsn: 'https://[email protected]/63',
Expand All @@ -37,7 +31,7 @@ const setupApp = memoize(() => {
ignoreErrors: [/^Warning: /]
})

return { root, client, lang, polyglot }
return { root, lang, polyglot }
})

export default setupApp
Loading