chore: show toast when duplicating note and update last modified date for duplicated note (#2379)
This commit is contained in:
@@ -11,7 +11,7 @@ import {
|
||||
import { ContentType } from '@standardnotes/domain-core'
|
||||
import { AlertService, InternalEventBusInterface } from '@standardnotes/services'
|
||||
import { MutatorService, PayloadManager, ItemManager } from '../'
|
||||
import { UuidGenerator } from '@standardnotes/utils'
|
||||
import { UuidGenerator, sleep } from '@standardnotes/utils'
|
||||
|
||||
const setupRandomUuid = () => {
|
||||
UuidGenerator.SetGenerator(() => String(Math.random()))
|
||||
@@ -65,6 +65,14 @@ describe('mutator service', () => {
|
||||
|
||||
expect(note.userModifiedDate).toEqual(pinnedNote?.userModifiedDate)
|
||||
})
|
||||
|
||||
it('should update the modification date of duplicated notes', async () => {
|
||||
const note = await insertNote('hello')
|
||||
await sleep(1, false, 'Delaying duplication by 1ms to create unique timestamps')
|
||||
const duplicatedNote = await mutatorService.duplicateItem(note)
|
||||
|
||||
expect(duplicatedNote.userModifiedDate.getTime()).toBeGreaterThan(note.userModifiedDate.getTime())
|
||||
})
|
||||
})
|
||||
|
||||
describe('linking', () => {
|
||||
|
||||
@@ -12,6 +12,7 @@ import { PayloadManager } from '../Payloads/PayloadManager'
|
||||
import { TagsToFoldersMigrationApplicator } from '@Lib/Migrations/Applicators/TagsToFolders'
|
||||
import {
|
||||
ActionsExtensionMutator,
|
||||
AppDataField,
|
||||
ComponentInterface,
|
||||
ComponentMutator,
|
||||
CreateDecryptedMutatorForItem,
|
||||
@@ -19,6 +20,7 @@ import {
|
||||
DecryptedItemMutator,
|
||||
DecryptedPayload,
|
||||
DecryptedPayloadInterface,
|
||||
DefaultAppDomain,
|
||||
DeleteItemMutator,
|
||||
EncryptedItemInterface,
|
||||
FeatureRepoMutator,
|
||||
@@ -319,7 +321,14 @@ export class MutatorService extends AbstractService implements MutatorClientInte
|
||||
payload,
|
||||
baseCollection: this.payloadManager.getMasterCollection(),
|
||||
isConflict,
|
||||
additionalContent,
|
||||
additionalContent: {
|
||||
appData: {
|
||||
[DefaultAppDomain]: {
|
||||
[AppDataField.UserModifiedDate]: new Date(),
|
||||
},
|
||||
},
|
||||
...additionalContent,
|
||||
},
|
||||
})
|
||||
|
||||
await this.payloadManager.emitPayloads(resultingPayloads, PayloadEmitSource.LocalChanged)
|
||||
|
||||
@@ -261,6 +261,7 @@ const ApplicationView: FunctionComponent<Props> = ({ application, mainApplicatio
|
||||
notesController={viewControllerManager.notesController}
|
||||
linkingController={viewControllerManager.linkingController}
|
||||
historyModalController={viewControllerManager.historyModalController}
|
||||
selectionController={viewControllerManager.selectionController}
|
||||
/>
|
||||
<TagContextMenuWrapper
|
||||
navigationController={viewControllerManager.navigationController}
|
||||
|
||||
@@ -381,6 +381,7 @@ const ContentListView = forwardRef<HTMLDivElement, Props>(
|
||||
notesController={notesController}
|
||||
historyModalController={historyModalController}
|
||||
itemListController={itemListController}
|
||||
selectionController={selectionController}
|
||||
/>
|
||||
) : (
|
||||
<ContentList
|
||||
|
||||
@@ -41,6 +41,7 @@ import { useItemLinks } from '@/Hooks/useItemLinks'
|
||||
import { ItemLink } from '@/Utils/Items/Search/ItemLink'
|
||||
import { ItemListController } from '@/Controllers/ItemList/ItemListController'
|
||||
import ListItemVaultInfo from '../ContentListView/ListItemVaultInfo'
|
||||
import { SelectedItemsController } from '@/Controllers/SelectedItemsController'
|
||||
|
||||
const ContextMenuCell = ({
|
||||
items,
|
||||
@@ -49,6 +50,7 @@ const ContextMenuCell = ({
|
||||
linkingController,
|
||||
notesController,
|
||||
historyModalController,
|
||||
selectionController,
|
||||
}: {
|
||||
items: DecryptedItemInterface[]
|
||||
filesController: FilesController
|
||||
@@ -56,6 +58,7 @@ const ContextMenuCell = ({
|
||||
linkingController: LinkingController
|
||||
notesController: NotesController
|
||||
historyModalController: HistoryModalController
|
||||
selectionController: SelectedItemsController
|
||||
}) => {
|
||||
const [contextMenuVisible, setContextMenuVisible] = useState(false)
|
||||
const anchorElementRef = useRef<HTMLButtonElement>(null)
|
||||
@@ -117,6 +120,7 @@ const ContextMenuCell = ({
|
||||
notesController={notesController}
|
||||
linkingController={linkingController}
|
||||
historyModalController={historyModalController}
|
||||
selectionController={selectionController}
|
||||
closeMenu={() => {
|
||||
setContextMenuVisible(false)
|
||||
}}
|
||||
@@ -266,6 +270,7 @@ type Props = {
|
||||
notesController: NotesController
|
||||
historyModalController: HistoryModalController
|
||||
itemListController: ItemListController
|
||||
selectionController: SelectedItemsController
|
||||
}
|
||||
|
||||
const ContentTableView = ({
|
||||
@@ -278,6 +283,7 @@ const ContentTableView = ({
|
||||
notesController,
|
||||
historyModalController,
|
||||
itemListController,
|
||||
selectionController,
|
||||
}: Props) => {
|
||||
const listHasFiles = items.some((item) => item instanceof FileItem)
|
||||
|
||||
@@ -406,6 +412,7 @@ const ContentTableView = ({
|
||||
navigationController={navigationController}
|
||||
notesController={notesController}
|
||||
historyModalController={historyModalController}
|
||||
selectionController={selectionController}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
@@ -418,6 +425,7 @@ const ContentTableView = ({
|
||||
navigationController={navigationController}
|
||||
notesController={notesController}
|
||||
historyModalController={historyModalController}
|
||||
selectionController={selectionController}
|
||||
/>
|
||||
),
|
||||
showSelectionActions: true,
|
||||
@@ -465,6 +473,7 @@ const ContentTableView = ({
|
||||
notesController={notesController}
|
||||
linkingController={linkingController}
|
||||
historyModalController={historyModalController}
|
||||
selectionController={selectionController}
|
||||
closeMenu={closeContextMenu}
|
||||
/>
|
||||
</Menu>
|
||||
|
||||
@@ -51,6 +51,7 @@ const MultipleSelectedNotes = ({
|
||||
notesController={notesController}
|
||||
linkingController={linkingController}
|
||||
historyModalController={historyModalController}
|
||||
selectionController={selectionController}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -932,6 +932,7 @@ class NoteView extends AbstractComponent<NoteViewProps, State> {
|
||||
notesController={this.viewControllerManager.notesController}
|
||||
linkingController={this.viewControllerManager.linkingController}
|
||||
historyModalController={this.viewControllerManager.historyModalController}
|
||||
selectionController={this.viewControllerManager.selectionController}
|
||||
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -7,12 +7,14 @@ import { HistoryModalController } from '@/Controllers/NoteHistory/HistoryModalCo
|
||||
import Popover from '../Popover/Popover'
|
||||
import { LinkingController } from '@/Controllers/LinkingController'
|
||||
import Menu from '../Menu/Menu'
|
||||
import { SelectedItemsController } from '@/Controllers/SelectedItemsController'
|
||||
|
||||
type Props = {
|
||||
navigationController: NavigationController
|
||||
notesController: NotesController
|
||||
linkingController: LinkingController
|
||||
historyModalController: HistoryModalController
|
||||
selectionController: SelectedItemsController
|
||||
}
|
||||
|
||||
const NotesContextMenu = ({
|
||||
@@ -20,6 +22,7 @@ const NotesContextMenu = ({
|
||||
notesController,
|
||||
linkingController,
|
||||
historyModalController,
|
||||
selectionController,
|
||||
}: Props) => {
|
||||
const { contextMenuOpen, contextMenuClickLocation, setContextMenuOpen } = notesController
|
||||
|
||||
@@ -50,6 +53,7 @@ const NotesContextMenu = ({
|
||||
notesController={notesController}
|
||||
linkingController={linkingController}
|
||||
historyModalController={historyModalController}
|
||||
selectionController={selectionController}
|
||||
requestDisableClickOutside={handleDisableClickOutsideRequest}
|
||||
closeMenu={closeMenu}
|
||||
/>
|
||||
|
||||
@@ -55,6 +55,7 @@ const NotesOptions = ({
|
||||
navigationController,
|
||||
notesController,
|
||||
linkingController,
|
||||
selectionController,
|
||||
historyModalController,
|
||||
closeMenu,
|
||||
}: NotesOptionsProps) => {
|
||||
@@ -150,10 +151,32 @@ const NotesOptions = ({
|
||||
}, [closeMenu, toggleAppPane])
|
||||
|
||||
const duplicateSelectedItems = useCallback(async () => {
|
||||
await Promise.all(notes.map((note) => application.mutator.duplicateItem(note).catch(console.error)))
|
||||
await Promise.all(
|
||||
notes.map((note) =>
|
||||
application.mutator
|
||||
.duplicateItem(note)
|
||||
.then((duplicated) =>
|
||||
addToast({
|
||||
type: ToastType.Regular,
|
||||
message: `Duplicated note "${duplicated.title}"`,
|
||||
actions: [
|
||||
{
|
||||
label: 'Open',
|
||||
handler: (toastId) => {
|
||||
selectionController.selectItem(duplicated.uuid, true).catch(console.error)
|
||||
dismissToast(toastId)
|
||||
},
|
||||
},
|
||||
],
|
||||
autoClose: true,
|
||||
}),
|
||||
)
|
||||
.catch(console.error),
|
||||
),
|
||||
)
|
||||
void application.sync.sync()
|
||||
closeMenuAndToggleNotesList()
|
||||
}, [application.mutator, application.sync, closeMenuAndToggleNotesList, notes])
|
||||
}, [application.mutator, application.sync, closeMenuAndToggleNotesList, notes, selectionController])
|
||||
|
||||
const openRevisionHistoryModal = useCallback(() => {
|
||||
historyModalController.openModal(notesController.firstSelectedNote)
|
||||
|
||||
@@ -8,12 +8,14 @@ import Popover from '../Popover/Popover'
|
||||
import { LinkingController } from '@/Controllers/LinkingController'
|
||||
import RoundIconButton from '../Button/RoundIconButton'
|
||||
import Menu from '../Menu/Menu'
|
||||
import { SelectedItemsController } from '@/Controllers/SelectedItemsController'
|
||||
|
||||
type Props = {
|
||||
navigationController: NavigationController
|
||||
notesController: NotesController
|
||||
linkingController: LinkingController
|
||||
historyModalController: HistoryModalController
|
||||
selectionController: SelectedItemsController
|
||||
onClickPreprocessing?: () => Promise<void>
|
||||
}
|
||||
|
||||
@@ -22,6 +24,7 @@ const NotesOptionsPanel = ({
|
||||
notesController,
|
||||
linkingController,
|
||||
historyModalController,
|
||||
selectionController,
|
||||
onClickPreprocessing,
|
||||
}: Props) => {
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
@@ -58,6 +61,7 @@ const NotesOptionsPanel = ({
|
||||
notesController={notesController}
|
||||
linkingController={linkingController}
|
||||
historyModalController={historyModalController}
|
||||
selectionController={selectionController}
|
||||
requestDisableClickOutside={handleDisableClickOutsideRequest}
|
||||
closeMenu={toggleMenu}
|
||||
/>
|
||||
|
||||
@@ -3,6 +3,7 @@ import { NavigationController } from '@/Controllers/Navigation/NavigationControl
|
||||
import { NotesController } from '@/Controllers/NotesController/NotesController'
|
||||
import { LinkingController } from '@/Controllers/LinkingController'
|
||||
import { SNNote } from '@standardnotes/snjs'
|
||||
import { SelectedItemsController } from '@/Controllers/SelectedItemsController'
|
||||
|
||||
export type NotesOptionsProps = {
|
||||
notes: SNNote[]
|
||||
@@ -10,6 +11,7 @@ export type NotesOptionsProps = {
|
||||
notesController: NotesController
|
||||
linkingController: LinkingController
|
||||
historyModalController: HistoryModalController
|
||||
selectionController: SelectedItemsController
|
||||
requestDisableClickOutside?: (disabled: boolean) => void
|
||||
closeMenu: () => void
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user