diff --git a/src/components/NotificationCard.vue b/src/components/NotificationCard.vue index 87ba210d..243c8c4c 100644 --- a/src/components/NotificationCard.vue +++ b/src/components/NotificationCard.vue @@ -110,6 +110,7 @@ Copyright © 2021 - present Aleksey Hoffman. All rights reserved. Directory: ${store.state.navigatorView.currentDir.path}` + notifications.emit({ + name: 'directoryWasReloaded', + props: { + currentDirPath: store.state.navigatorView.currentDir.path + } }) } } @@ -3033,9 +2994,17 @@ export default new Vuex.Store({ * @param {string[]} params.source */ ADD_TO_ARCHIVE (store, params) { + let archiveState = { + isCanceled: false, + error: false + } + let notification = {} + let hashID = utils.getHash() + if (params.source === 'target-items') { params.source = store.state.contextMenus.dirItem.targetItemsStats.dirItemsPaths } + if (params.dest) { params.dest = utils.getUniquePath(params.dest) } @@ -3044,7 +3013,8 @@ export default new Vuex.Store({ const uniqueDestPath = utils.getUniquePath(PATH.join(parsed.dir, 'Archive.zip')) params.dest = uniqueDestPath } - const appBinExtractStream = node7z.add( + + const archiveStream = node7z.add( params.dest, params.source, { @@ -3052,24 +3022,66 @@ export default new Vuex.Store({ $progress: true } ) - appBinExtractStream.on('error', (error) => { - new Notification({ - name: 'errorCannotAddToArchive', + + archiveStream.on('error', (error) => { + archiveState.error = true + notifications.emit({ + name: 'archiveAddDataError', error }) }) - appBinExtractStream.on('end', () => { - new Notification({ - name: 'archiveWasCreated', - message: params.dest + + archiveStream.on('progress', (progress) => { + notification = notifications.emit({ + name: 'archiveCreationProgress', + props: { + hashID, + progress, + params, + archiveStream, + archiveState + } }) }) + + archiveStream.on('end', () => { + if (!archiveState.error) { + if (!archiveState.isCanceled) { + setTimeout(() => { + console.log('progress, params', notification.progress, params) + notification.update({ + name: 'archiveWasCreated', + props: { + progress: notification.progress, + params, + hashID + } + }) + }, 1000) + } + else { + notification.update({ + name: 'archiveCreationCanceled', + props: { + hashID + } + }) + } + } + }) }, /** * @param {string} params.dest * @param {string} params.source */ EXTRACT_ARCHIVE (store, params) { + let archiveState = { + isCanceled: false, + error: false + } + let notification = {} + let hashID = utils.getHash() + if (params.source === 'target-items') { params.source = store.state.contextMenus.dirItem.targetItemsStats.dirItemsPaths[0] } @@ -3080,27 +3092,7 @@ export default new Vuex.Store({ params.dest = dest } - const hash = utils.getHash() - - let state = { - isCanceled: false, - error: false - } - - let notification = { - progress: { - percent: 0, - fileCount: 0, - file: '' - }, - action: 'update-by-type', - hash, - type: `archiver:extract-progress-${hash}`, - colorStatus: 'blue', - timeout: 0, - } - - const appBinExtractStream = node7z.extractFull( + const archiveStream = node7z.extractFull( params.source, params.dest, { @@ -3109,55 +3101,49 @@ export default new Vuex.Store({ } ) - appBinExtractStream.on('error', (error) => { - state.error = true - eventHub.$emit('notification', { - action: 'update-by-type', - type: 'archiver:extract-error', - colorStatus: 'red', - timeout: 5000, - title: 'Error: cannot extract the archive', - message: error + archiveStream.on('error', (error) => { + archiveState.error = true + notifications.emit({ + name: 'archiveExtractionError', + error }) }) - - appBinExtractStream.on('progress', (progress) => { - notification.progress = progress - notification.title = 'Extracting archive' - notification.message = ` - ${notification.progress.percent}% • - ${notification.progress.fileCount} files -
Archive: ${params.source} - ` - notification.actionButtons = [ - { - title: 'cancel', - onClick: () => { - appBinExtractStream._childProcess.kill() - state.isCanceled = true - } + + archiveStream.on('progress', (progress) => { + notification = notifications.emit({ + name: 'archiveExtractionProgress', + props: { + hashID, + progress, + params, + archiveStream, + archiveState } - ] - eventHub.$emit('notification', notification) + }) }) - - appBinExtractStream.on('end', () => { - notification.timeout = 5000 - notification.actionButtons = [] - notification.message = ` - Done • ${notification.progress.fileCount} files -
Destination: ${params.dest} - ` - if (!state.error) { - if (!state.isCanceled) { - notification.colorStatus = 'teal' - notification.title = 'Archive was extracted' - eventHub.$emit('notification', notification) + + archiveStream.on('end', () => { + if (!archiveState.error) { + if (!archiveState.isCanceled) { + setTimeout(() => { + console.log('progress, params', notification.progress, params) + notification.update({ + name: 'archiveWasExtracted', + props: { + progress: notification.progress, + params, + hashID + } + }) + }, 1000) } else { - notification.colorStatus = 'red' - notification.title = 'Archive extraction canceled', - eventHub.$emit('notification', notification) + notification.update({ + name: 'archiveExtractionCanceled', + props: { + hashID + } + }) } } }) @@ -3998,19 +3984,8 @@ export default new Vuex.Store({ key: 'storageData.notes.items', value: state.storageData.notes.items }) - eventHub.$emit('notification', { - action: 'add', - actionButtons: [ - { - title: 'Undo', - action: 'undoTrashNote', - closesNotification: true - } - ], - closeButton: true, - timeout: 10000, - title: 'Note has been trashed', - message: 'Switch to "trashed notes" list to see all trashed notes' + notifications.emit({ + name: 'noteWasTrashed' }) }, RESTORE_NOTE_FROM_TRASH ({ state, commit, dispatch, getters }, note) { @@ -4360,17 +4335,16 @@ export default new Vuex.Store({ } store.state.contextMenus[params.type].targetItemsStats = data }, - SET_PINNED (store, payload) { + async SET_PINNED (store, payload) { let items = payload ? payload : store.getters.selectedDirItems let pinnedItems = utils.cloneDeep(store.state.storageData.pinned.items) const allSelectedArePinned = checkAllSelectedArePinned() let itemCounter = 0 - let notificationParams = {} let itemToAdd = {} let itemPropertiesToStore = ['path'] processItems() - setStorage() + await setStorage() setNotification() function checkAllSelectedArePinned () { @@ -4383,13 +4357,9 @@ export default new Vuex.Store({ function processItems () { if (allSelectedArePinned) { removeItems() - notificationParams.type = 'success:removedFromPinned' - notificationParams.title = `Removed ${itemCounter} items from pinned` } else { setItems() - notificationParams.type = 'success:addedToPinned' - notificationParams.title = `Added ${itemCounter} items to pinned` } } @@ -4422,16 +4392,25 @@ export default new Vuex.Store({ } function setNotification () { - eventHub.$emit('notification', { - action: 'update-by-type', - type: notificationParams.type, - timeout: 2000, - closeButton: true, - title: notificationParams.title, - }) + if (allSelectedArePinned) { + notifications.emit({ + name: 'removedFromPinnedSuccess', + props: { + itemCounter + } + }) + } + else { + notifications.emit({ + name: 'addedToPinnedSuccess', + props: { + itemCounter + } + }) + } } - function setStorage () { + async function setStorage () { store.dispatch('SET', { key: 'storageData.pinned.items', value: pinnedItems @@ -4441,9 +4420,8 @@ export default new Vuex.Store({ /** * @param {array} payload */ - SET_PROTECTED (store, payload) { + async SET_PROTECTED (store, payload) { let itemCounter = 0 - let notificationParams = {} let itemToAdd = {} let itemPropertiesToStore = ['path'] @@ -4454,14 +4432,12 @@ export default new Vuex.Store({ }) processItems() - setStorage() + await setStorage() setNotification() function processItems () { if (everySelectedIsProtected) { removeItems() - notificationParams.type = 'success:removedFromPinned' - notificationParams.title = `Removed ${itemCounter} items from protected` // Set permissions // const permissions = { // owner: 7, @@ -4472,8 +4448,6 @@ export default new Vuex.Store({ } else { setItems() - notificationParams.type = 'success:addedToProtected' - notificationParams.title = `Added ${itemCounter} items to protected` // Set permissions // const permissions = { // owner: 4, @@ -4513,16 +4487,25 @@ export default new Vuex.Store({ } function setNotification () { - eventHub.$emit('notification', { - action: 'update-by-type', - type: notificationParams.type, - timeout: 2000, - closeButton: true, - title: notificationParams.title, - }) + if (everySelectedIsProtected) { + notifications.emit({ + name: 'removedFromProtectedSuccess', + props: { + itemCounter + } + }) + } + else { + notifications.emit({ + name: 'addedToProtectedSuccess', + props: { + itemCounter + } + }) + } } - function setStorage () { + async function setStorage () { store.dispatch('SET', { key: 'storageData.protected.items', value: protectedItems @@ -4532,22 +4515,14 @@ export default new Vuex.Store({ async SET_DIR_ITEM_PERMISSIONS (store, params) { try { await fsManager.changeMode(params) - eventHub.$emit('notification', { - action: 'update-by-type', - type: 'success:setDirItemPermissions', - timeout: 3000, - closeButton: true, - title: `Permissions were changed`, + notifications.emit({ + name: 'setDirItemPermissionsSuccess' }) } catch (error) { - eventHub.$emit('notification', { - action: 'update-by-type', - type: 'error:setDirItemPermissions', - timeout: 3000, - closeButton: true, - title: `Failed to change permissions`, - message: `${error}` + notifications.emit({ + name: 'setDirItemPermissionsFailure', + error }) } }, @@ -4861,7 +4836,7 @@ export default new Vuex.Store({ ...params } - let notification = new Notification({name: 'copyDirItemsInProgress'}) + let notification = notifications.emit({name: 'copyDirItemsInProgress'}) showInProgressNotification() await copyItems(params) @@ -4920,10 +4895,20 @@ export default new Vuex.Store({ function showSuccessNotification () { if (params.operation === 'move') { - notification.update({name: 'moveDirItemsSuccess', format: {items: params.items.length}}) + notification.update({ + name: 'moveDirItemsSuccess', + props: { + items: params.items.length + } + }) } else if (params.operation === 'copy') { - notification.update({name: 'copyDirItemsSuccess', format: {items: params.items.length}}) + notification.update({ + name: 'copyDirItemsSuccess', + props: { + items: params.items.length + } + }) } } @@ -5328,34 +5313,17 @@ export default new Vuex.Store({ } }) }, - HANDLE_APP_UPDATE_UNAVAILABLE ({ state, commit, dispatch, getters }, payload) { - const { latestVersion, notifyUnavailable } = payload + HANDLE_APP_UPDATE_UNAVAILABLE (store, payload) { + const {latestVersion, notifyUnavailable} = payload if (notifyUnavailable) { - eventHub.$emit('notification', { - action: 'update-by-type', - type: 'update:unavailable', - timeout: 5000, - colorStatus: 'blue', - isPinned: true, - removeWhenHidden: false, - title: 'No updates available', - message: ` - Current version: ${state.appVersion} -
Latest version: ${latestVersion} - `, - closeButton: true, - actionButtons: [ - { - title: 'Project page', - action: '', - extrnalLink: state.appPaths.githubRepoLink, - onClick: () => { - utils.openLink(state.appPaths.githubRepoLink) - }, - closesNotification: false - } - ] + notifications.emit({ + name: 'updateUnavailable', + props: { + state: store.state, + utils, + latestVersion + } }) } }, @@ -5402,50 +5370,18 @@ export default new Vuex.Store({ actionButtons }) }, - HANDLE_APP_UPDATE_DOWNLOADED ({ state, commit, dispatch, getters }, payload) { - const { latestVersion, info } = payload - // Remove 'progress' notification - eventHub.$emit('notification', { - action: 'hide', - hashID: info.hashID - }) - - const actionButtons = [ - { - title: 'install update', - action: '', - onClick: () => { - dispatch('OPEN_FILE', `${state.appPaths.updateDownloadDir}/${info.filename}`) - }, - closesNotification: true - }, - { - title: 'show in directory', - action: 'showDownloadedFile', - closesNotification: false, - onClick: () => { - dispatch('SHOW_DIR_ITEM_IN_DIRECTORY', { dir: info.dir, itemPath: info.filePath }) - } + HANDLE_APP_UPDATE_DOWNLOADED (store, params) { + const {latestVersion, info} = params + notifications.hideByHashID(info.hashID) + notifications.emit({ + name: 'updateWasDownloaded', + props: { + store, + latestVersion, + info } - ] - - // Push 'update was downloaded' notification - eventHub.$emit('notification', { - action: 'add', - type: 'update:downloaded', - colorStatus: 'blue', - isPinned: true, - isUpdate: true, - removeWhenHidden: false, - timeout: 0, - title: `Update downloaded: v${latestVersion}`, - message: 'Press install to close the app and update it', - closeButton: true, - actionButtons }) - - // Remove "update-available" item from notifications list - state.notifications = state.notifications.filter(item => item.type !== 'update-available') + store.state.notifications = store.state.notifications.filter(item => item.type !== 'update-available') }, DOWNLOAD_APP_UPDATE (store, params) { electron.ipcRenderer.send('download-file', { diff --git a/src/utils/notifications.js b/src/utils/notifications.js index 9f6849a1..2a3e49ec 100644 --- a/src/utils/notifications.js +++ b/src/utils/notifications.js @@ -2,205 +2,528 @@ // License: GNU GPLv3 or later. See the license file in the project root for more information. // Copyright © 2021 - present Aleksey Hoffman. All rights reserved. -import utils from './sharedUtils.js' -import localizeUtils from './localizeUtils.js' +import sharedUtils from './sharedUtils.js' const eventHub = require('./eventHub').eventHub -class Notification { - constructor (params) { - this.notifications = { - copyDirItemsInProgress: { - action: 'update-by-hash', - hashID: utils.getHash(), - type: 'dir-item-transfer', - icon: 'mdi-progress-clock', - colorStatus: 'blue', - closeButton: true, - timeout: 0, - title: 'In progress: copying items' - }, - copyDirItemsSuccess: { - action: 'update-by-hash', - hashID: utils.getHash(), - type: 'dir-item-transfer', - colorStatus: 'green', - icon: '', - closeButton: true, - timeout: 3000, - title: 'Copied {{items}}' - }, - moveDirItemsInProgress: { - action: 'update-by-hash', - hashID: utils.getHash(), - type: 'dir-item-transfer', - icon: 'mdi-progress-clock', - colorStatus: 'blue', - closeButton: true, - timeout: 0, - title: 'In progress: moving items' - }, - moveDirItemsSuccess: { - action: 'update-by-hash', - hashID: utils.getHash(), - type: 'dir-item-transfer', - colorStatus: 'green', - icon: '', - closeButton: true, - timeout: 3000, - title: 'Moved {{items}}' - }, - transferDirItemsError: { - action: 'update-by-hash', - hashID: utils.getHash(), - type: 'dir-item-transfer', - icon: 'mdi-progress-close', - colorStatus: 'red', - closeButton: true, - timeout: 5000, - title: 'Error during transfer' - }, - renameFailedNoLongerExists: { - action: 'add', - colorStatus: 'red', - timeout: 6000, - closeButton: true, - title: 'Failed to rename item', - message: ` - File / directory that you are renaming no longer exists: -
Path: {{oldPath}} - ` - }, - renameFailedError: { - action: 'add', - colorStatus: 'red', - timeout: 6000, - closeButton: true, - title: 'Failed to rename item', - }, - renameFailedAlreadyExists: { - action: 'add', - colorStatus: 'red', - timeout: 5000, - closeButton: true, - title: 'Failed to rename item', - message: ` - Item with that name already exists: -
{{newName}} - ` - }, - renameSuccess: { - action: 'add', - colorStatus: 'green', - timeout: 3000, - closeButton: true, - title: 'Rename undone', - message: '' - }, - tabRemoved: { - action: 'update-by-type', - type: 'tab-removed', - timeout: 3000, - closeButton: true, - title: 'Removed tab from current workspace', - message: `{{tabPath}}` - }, - tabAdded: { - action: 'update-by-type', - type: 'tab-added', - timeout: 3000, - closeButton: true, - title: 'Tab added to current workspace', - message: ` - Shortcut to open: - {{tabShortcut}} - ` - }, - tabIsAlreadyOpened: { - action: 'update-by-type', - type: 'tab-added', - timeout: 5000, - closeButton: true, - title: 'Tab for this directory is already opened', - message: ` - Position: {{tabIndex}} - ` - }, - closedAllTabsInCurrentWorkspace: { - action: 'update-by-type', - type: 'closed-all-tabs-in-current-workspace', - timeout: 3000, - closeButton: true, - title: 'Closed all tabs in current workspace' - }, - currentWorkspaceHasNoTabs: { - action: 'update-by-type', - type: 'current-workspace-has-no-tabs', - timeout: 3000, - closeButton: true, - title: 'Current workspace has no tabs' - }, - errorCannotAddToArchive: { - action: 'update-by-type', - type: 'error:archiver:add', - timeout: 5000, - title: 'Error: cannot add data to the archive' - }, - archiveWasCreated: { - action: 'update-by-type', - type: 'archiver:add', - timeout: 5000, - title: 'Archive was created' - }, - } - - this.data = this.notifications[params.name] - if (params.format || params.error || params.props) { - this.update(params) - } - else { - eventHub.$emit('notification', this.data) - } - } - - update (params) { - let newNotification = this.notifications[params.name] - for (const [key, value] of Object.entries(newNotification)) { - if (!['hashID', 'id'].includes(key)) { - this.data[key] = value - this._formatProp({key, value, params}) - } - } - if (params.error) { - this.data.message = ` - Error: ${params.error} +/** +* @param {object} params +* @returns {object} +*/ +function getNotification (params) { + let notifications = { + copyDirItemsInProgress: { + action: 'update-by-hash', + hashID: sharedUtils.getHash(), + type: 'copyDirItemsInProgress', + icon: 'mdi-progress-clock', + colorStatus: 'blue', + closeButton: true, + timeout: 0, + title: 'In progress: copying items' + }, + copyDirItemsSuccess: { + action: 'update-by-hash', + hashID: sharedUtils.getHash(), + type: 'copyDirItemsSuccess', + colorStatus: 'green', + icon: '', + closeButton: true, + timeout: 3000, + title: `Copied ${params?.props?.items} items` + }, + moveDirItemsInProgress: { + action: 'update-by-hash', + hashID: sharedUtils.getHash(), + type: 'moveDirItemsInProgress', + icon: 'mdi-progress-clock', + colorStatus: 'blue', + closeButton: true, + timeout: 0, + title: 'In progress: moving items' + }, + moveDirItemsSuccess: { + action: 'update-by-hash', + hashID: sharedUtils.getHash(), + type: 'moveDirItemsSuccess', + colorStatus: 'green', + icon: '', + closeButton: true, + timeout: 3000, + title: `Moved ${params?.props?.items} items` + }, + transferDirItemsError: { + action: 'update-by-hash', + hashID: sharedUtils.getHash(), + type: 'transferDirItemsError', + icon: 'mdi-progress-close', + colorStatus: 'red', + closeButton: true, + timeout: 5000, + title: 'Error during transfer', + error: params?.props?.error + }, + renameFailedNoLongerExists: { + action: 'add', + colorStatus: 'red', + timeout: 6000, + closeButton: true, + title: 'Failed to rename item', + message: ` + File / directory that you are renaming no longer exists: +
Path: ${params?.props?.oldPath} ` - } - if (params.props) { - for (const [key, value] of Object.entries(params.props)) { - this.data[key] = value - } - } - eventHub.$emit('notification', this.data) - } - - hide () { - this.data.action = 'hide' - eventHub.$emit('notification', this.data) - } - - _formatProp (scope1Params) { - if (scope1Params.params.format) { - if (typeof scope1Params.value === 'string') { - for (const [formatKey, formatValue] of Object.entries(scope1Params.params.format)) { - let formattedText = formatValue - if (formatKey === 'items') { - formattedText = `${formatValue} ${localizeUtils.pluralize(formatValue, 'item')}` + }, + renameFailedError: { + action: 'add', + colorStatus: 'red', + timeout: 6000, + closeButton: true, + title: 'Failed to rename item', + error: params?.props?.error + }, + renameFailedAlreadyExistsOrLocked: { + action: 'add', + colorStatus: 'red', + timeout: 5000, + closeButton: true, + title: 'Failed to rename item', + message: ` + Item with that name already exists or locked by another program: +
${params?.props?.newName} + ` + }, + renameSuccess: { + action: 'add', + colorStatus: 'green', + timeout: 3000, + closeButton: true, + title: 'Rename undone', + message: '' + }, + tabRemoved: { + action: 'update-by-type', + type: 'tabRemoved', + timeout: 3000, + closeButton: true, + title: 'Removed tab from current workspace', + message: `${params?.props?.tabPath}` + }, + tabAdded: { + action: 'update-by-type', + type: 'tabAdded', + timeout: 3000, + closeButton: true, + title: 'Tab added to current workspace', + message: ` + Shortcut to open: + ${params?.props?.tabShortcut} + ` + }, + tabIsAlreadyOpened: { + action: 'update-by-type', + type: 'tabIsAlreadyOpened', + timeout: 5000, + closeButton: true, + title: 'Tab for this directory is already opened', + message: ` + Position: ${params?.props?.tabIndex} + ` + }, + closedAllTabsInCurrentWorkspace: { + action: 'update-by-type', + type: 'closedAllTabsInCurrentWorkspace', + timeout: 3000, + closeButton: true, + title: 'Closed all tabs in current workspace' + }, + currentWorkspaceHasNoTabs: { + action: 'update-by-type', + type: 'currentWorkspaceHasNoTabs', + timeout: 3000, + closeButton: true, + title: 'Current workspace has no tabs' + }, + archiveAddDataError: { + action: 'update-by-type', + type: 'archiveAddDataError', + timeout: 5000, + title: 'Error: cannot add data to the archive', + error: params?.props?.error + }, + archiveExtractionError: { + action: 'update-by-type', + type: 'archiveExtractionError', + timeout: 2000, + title: 'Error: cannot extract archive', + error: params?.props?.error + }, + archiveExtractionCanceled: { + action: 'update-by-hash', + hashID: params?.props?.hashID, + type: 'archiveExtractionCanceled', + timeout: 3000, + actionButtons: [], + colorStatus: 'red', + title: 'Archive extraction canceled' + }, + archiveCreationCanceled: { + action: 'update-by-hash', + hashID: params?.props?.hashID, + type: 'archiveCreationCanceled', + timeout: 3000, + actionButtons: [], + colorStatus: 'red', + title: 'Archive creation canceled' + }, + archiveWasCreated: { + action: 'update-by-hash', + hashID: params?.props?.hashID, + type: 'archiveWasCreated', + timeout: 5000, + actionButtons: [], + colorStatus: 'green', + title: 'Archive was created', + message: ` + Done • ${params?.props?.progress?.fileCount} files +
Destination: ${params?.props?.params?.dest} + `, + }, + archiveWasExtracted: { + action: 'update-by-hash', + hashID: params?.props?.hashID, + type: 'archiveWasExtracted', + timeout: 5000, + actionButtons: [], + colorStatus: 'green', + title: 'Archive was extracted', + message: ` + Done • ${params?.props?.progress?.fileCount} files +
Destination: ${params?.props?.params?.dest} + `, + }, + archiveCreationProgress: { + action: 'update-by-hash', + hashID: params?.props?.hashID, + progress: params?.props?.progress, + timeout: 0, + title: 'Creating archive', + message: ` + ${params?.props?.progress?.percent}% • + ${params?.props?.progress?.fileCount} files +
Source: ${params?.props?.params?.source} +
Destination: ${params?.props?.params?.dest} + `, + actionButtons: [ + { + title: 'cancel', + onClick: () => { + params?.props?.archiveStream?._childProcess.kill() + params.props.archiveState.isCanceled = true } - this.data[scope1Params.key] = scope1Params.value.replace(`{{${formatKey}}}`, formattedText) } - } + ] + }, + archiveExtractionProgress: { + action: 'update-by-hash', + hashID: params?.props?.hashID, + progress: params?.props?.progress, + timeout: 0, + title: 'Extracting archive', + message: ` + ${params?.props?.progress?.percent}% • + ${params?.props?.progress?.fileCount} files +
Source: ${params?.props?.params?.source} +
Destination: ${params?.props?.params?.dest} + `, + actionButtons: [ + { + title: 'cancel', + onClick: () => { + params?.props?.archiveStream?._childProcess.kill() + params.props.archiveState.isCanceled = true + } + } + ] + }, + cannotDeleteDriveRootDir: { + action: 'update-by-type', + type: 'cannotDeleteDriveRootDir', + icon: 'mdi-delete-forever-outline', + timeout: 3000, + title: `You cannot delete drive's root directory` + }, + trashItemsSuccess: { + action: 'update-by-type', + type: 'trashItemsSuccess', + icon: 'mdi-trash-can-outline', + colorStatus: 'green', + timeout: 5000, + title: `All items were trashed`, + message: ` + Items: + ${params?.props?.trashedItems?.length} + • Size: + ${params?.props?.trashedItemsSize} + `, + }, + trashItemsFailure: { + action: 'update-by-type', + type: 'trashItemsFailure', + icon: 'mdi-trash-can-outline', + colorStatus: 'red', + timeout: 5000, + title: `Failed to trash some items`, + message: ` + Trashed items: + ${params?.props?.items?.length} + of + ${params?.props?.notTrashedItems?.length} +
Total size: +
Could not trash: +
${params?.props?.notTrashedItems?.join('
')} + `, + }, + deleteItemsSuccess: { + action: 'update-by-type', + type: 'deleteItemsSuccess', + icon: 'mdi-delete-forever-outline', + colorStatus: 'green', + timeout: 5000, + title: `All items were deleted`, + message: ` + Items: + ${params?.props?.deletedItems?.length} + • Size: + ${params?.props?.deletedItemsSize} + `, + }, + deleteItemsFailure: { + action: 'update-by-type', + type: 'deleteItemsFailure', + icon: 'mdi-delete-forever-outline', + colorStatus: 'red', + timeout: 5000, + title: `Failed to delete some items`, + message: ` + Deleted items: + ${params?.props?.items?.length} + of + ${params?.props?.notDeletedItems?.length} +
Total size: +
Could not delete: +
${params?.props?.notDeletedItems?.join('
')} + `, + }, + noteWasTrashed: { + action: 'add', + actionButtons: [ + { + title: 'Undo', + action: 'undoTrashNote', + closesNotification: true + } + ], + closeButton: true, + timeout: 10000, + title: 'Note was trashed', + message: 'Switch to "trashed notes" list to see all trashed notes' + }, + removedFromPinnedSuccess: { + action: 'update-by-type', + type: 'removedFromPinnedSuccess', + timeout: 2000, + closeButton: true, + title: `Removed ${params?.props?.itemCounter} items from pinned`, + }, + addedToPinnedSuccess: { + action: 'update-by-type', + type: 'addedToPinnedSuccess', + timeout: 2000, + closeButton: true, + title: `Added ${params?.props?.itemCounter} items to pinned`, + }, + removedFromProtectedSuccess: { + action: 'update-by-type', + type: 'removedFromProtectedSuccess', + timeout: 2000, + closeButton: true, + title: `Removed ${params?.props?.itemCounter} items from protected`, + }, + addedToProtectedSuccess: { + action: 'update-by-type', + type: 'addedToProtectedSuccess', + timeout: 2000, + closeButton: true, + title: `Added ${params?.props?.itemCounter} items to protected`, + }, + actionNotAllowedWhenInputFieldIsActive: { + action: 'update-by-type', + type: 'actionFailed', + timeout: 3000, + closeButton: true, + title: 'Action failed', + message: 'Action is not allowed when input field is active' + }, + actionNotAllowedWhenDialogIsOpened: { + action: 'update-by-type', + type: 'actionFailed', + timeout: 3000, + closeButton: true, + title: 'Action failed', + message: 'Action is not allowed when a dialog is opened' + }, + actionFailedNoDirItemsSelected: { + action: 'update-by-type', + type: 'actionFailed', + timeout: 3000, + closeButton: true, + title: 'Action failed', + message: 'No directory items are selected' + }, + actionNotAllowedOnThisPage: { + action: 'update-by-type', + type: 'actionFailed', + timeout: 3000, + closeButton: true, + title: 'Action failed', + message: 'Action is not allowed on this page' + }, + increaseUIZoom: { + action: 'update-by-type', + type: 'UIZoomChange', + timeout: 2000, + title: `UI scale changed: ${params?.props?.newZoomFactor}%` + }, + decreaseUIZoom: { + action: 'update-by-type', + type: 'UIZoomChange', + timeout: 2000, + title: `UI scale changed: ${params?.props?.newZoomFactor}%` + }, + resetUIZoom: { + action: 'update-by-type', + type: 'UIZoomChange', + timeout: 2000, + title: `UI scale changed: 100%` + }, + directoryWasReloaded: { + action: 'update-by-type', + type: 'directoryWasReloaded', + timeout: 2000, + title: 'Directory was reloaded', + message: `Directory: ${params?.props?.currentDirPath}` + }, + setDirItemPermissionsSuccess: { + action: 'update-by-type', + type: 'setDirItemPermissionsSuccess', + timeout: 3000, + closeButton: true, + title: 'Permissions were changed', + }, + setDirItemPermissionsFailure: { + action: 'update-by-type', + type: 'setDirItemPermissionsFailure', + timeout: 3000, + closeButton: true, + title: 'Failed to change permissions', + error: params?.props?.error + }, + updateUnavailable: { + action: 'update-by-type', + type: 'updateUnavailable', + timeout: 5000, + colorStatus: 'blue', + isPinned: true, + removeWhenHidden: false, + title: 'No updates available', + message: ` + Current version: ${params?.props?.state?.appVersion} +
Latest version: ${params?.props?.latestVersion} + `, + closeButton: true, + actionButtons: [ + { + title: 'Project page', + action: '', + extrnalLink: params?.props?.state?.appPaths?.githubRepoLink, + onClick: () => { + params?.props?.utils.openLink(params?.props?.state?.appPaths?.githubRepoLink) + }, + closesNotification: false + } + ] + }, + updateWasDownloaded: { + action: 'add', + type: 'updateWasDownloaded', + colorStatus: 'blue', + isPinned: true, + isUpdate: true, + removeWhenHidden: false, + timeout: 0, + title: `Update downloaded: v${params?.props?.latestVersion}`, + message: 'Press install to close the app and update it', + closeButton: true, + actionButtons: [ + { + title: 'install update', + action: '', + onClick: () => { + let updateFileDownloadDir = params?.props?.store?.state?.appPaths?.updateDownloadDir + let updateFileName = params?.props?.info?.filename + let updateFilePath = `${updateFileDownloadDir}/${updateFileName}` + params?.props?.store?.dispatch('OPEN_FILE', updateFilePath) + }, + closesNotification: true + }, + { + title: 'show in directory', + action: 'showDownloadedFile', + closesNotification: false, + onClick: () => { + params?.props?.store?.dispatch('SHOW_DIR_ITEM_IN_DIRECTORY', { + dir: params?.props?.info?.dir, + itemPath: params?.props?.info?.filePath + }) + } + } + ] + }, + } + return notifications[params.name] +} + +function emit (params) { + let notification = getNotification(params) + notification.hide = () => hide(notification) + notification.update = (params) => update(notification, params) + eventHub.$emit('notification', notification) + return notification +} + +function update (notification, params) { + let newNotification = getNotification(params) + for (const [key, value] of Object.entries(newNotification)) { + if (!['hashID', 'id'].includes(key)) { + notification[key] = value } } + eventHub.$emit('notification', notification) +} + +function hide (notification) { + notification.action = 'hide' + update(notification) +} + +function hideByHashID (hashID) { + eventHub.$emit('notification', { + action: 'hide', + hashID + }) } -export default Notification \ No newline at end of file +export { + emit, + hideByHashID +} \ No newline at end of file