feat: dedicated files layout (#1928)
This commit is contained in:
@@ -22,6 +22,7 @@ import {
|
||||
useBoolean,
|
||||
TemplateNoteViewAutofocusBehavior,
|
||||
isTag,
|
||||
isFile,
|
||||
} from '@standardnotes/snjs'
|
||||
import { action, computed, makeObservable, observable, reaction, runInAction } from 'mobx'
|
||||
import { WebApplication } from '../../Application/Application'
|
||||
@@ -37,6 +38,7 @@ import dayjs from 'dayjs'
|
||||
import { LinkingController } from '../LinkingController'
|
||||
import { AbstractViewController } from '../Abstract/AbstractViewController'
|
||||
import { Persistable } from '../Abstract/Persistable'
|
||||
import { log, LoggingDomain } from '@/Logging'
|
||||
|
||||
const MinNoteCellHeight = 51.0
|
||||
const DefaultListNumNotes = 20
|
||||
@@ -380,11 +382,42 @@ export class ItemListController
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* In some cases we want to keep the selected item open even if it doesn't appear in results,
|
||||
* for example if you are inside tag Foo and remove tag Foo from the note, we want to keep the note open.
|
||||
*/
|
||||
private shouldCloseActiveItem = (activeItem: SNNote | FileItem | undefined) => {
|
||||
const isSearching = this.noteFilterText.length > 0
|
||||
const itemExistsInUpdatedResults = this.items.find((item) => item.uuid === activeItem?.uuid)
|
||||
const activeItemExistsInUpdatedResults = this.items.find((item) => item.uuid === activeItem?.uuid)
|
||||
|
||||
return !itemExistsInUpdatedResults && !isSearching && this.navigationController.isInAnySystemView()
|
||||
const closeBecauseActiveItemIsFileAndDoesntExistInUpdatedResults =
|
||||
activeItem && isFile(activeItem) && !activeItemExistsInUpdatedResults
|
||||
|
||||
if (closeBecauseActiveItemIsFileAndDoesntExistInUpdatedResults) {
|
||||
log(LoggingDomain.Selection, 'shouldCloseActiveItem closeBecauseActiveItemIsFileAndDoesntExistInUpdatedResults')
|
||||
return true
|
||||
}
|
||||
|
||||
const firstItemInNewResults = this.getFirstNonProtectedItem()
|
||||
|
||||
const closePreviousItemWhenSwitchingToFilesBasedView =
|
||||
firstItemInNewResults && isFile(firstItemInNewResults) && !activeItemExistsInUpdatedResults
|
||||
|
||||
if (closePreviousItemWhenSwitchingToFilesBasedView) {
|
||||
log(LoggingDomain.Selection, 'shouldCloseActiveItem closePreviousItemWhenSwitchingToFilesBasedView')
|
||||
return true
|
||||
}
|
||||
|
||||
const isSearching = this.noteFilterText.length > 0
|
||||
|
||||
const closeBecauseActiveItemDoesntExistInCurrentSystemView =
|
||||
!activeItemExistsInUpdatedResults && !isSearching && this.navigationController.isInAnySystemView()
|
||||
|
||||
if (closeBecauseActiveItemDoesntExistInCurrentSystemView) {
|
||||
log(LoggingDomain.Selection, 'shouldCloseActiveItem closePreviousItemWhenSwitchingToFilesBasedView')
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private shouldSelectNextItemOrCreateNewNote = (activeItem: SNNote | FileItem | undefined) => {
|
||||
@@ -404,6 +437,11 @@ export class ItemListController
|
||||
}
|
||||
|
||||
private shouldSelectFirstItem = (itemsReloadSource: ItemsReloadSource) => {
|
||||
const item = this.getFirstNonProtectedItem()
|
||||
if (item && isFile(item)) {
|
||||
return false
|
||||
}
|
||||
|
||||
const selectedTag = this.navigationController.selected
|
||||
const isDailyEntry = selectedTag && isTag(selectedTag) && selectedTag.isDailyEntry
|
||||
if (isDailyEntry) {
|
||||
@@ -424,10 +462,17 @@ export class ItemListController
|
||||
|
||||
const activeItem = activeController?.item
|
||||
|
||||
if (this.shouldCloseActiveItem(activeItem) && activeController) {
|
||||
if (activeController && activeItem && this.shouldCloseActiveItem(activeItem)) {
|
||||
this.closeItemController(activeController)
|
||||
this.selectionController.selectNextItem()
|
||||
|
||||
this.selectionController.deselectItem(activeItem)
|
||||
|
||||
if (this.shouldSelectFirstItem(itemsReloadSource)) {
|
||||
log(LoggingDomain.Selection, 'Selecting next item after closing active one')
|
||||
this.selectionController.selectNextItem()
|
||||
}
|
||||
} else if (this.shouldSelectActiveItem(activeItem) && activeItem) {
|
||||
log(LoggingDomain.Selection, 'Selecting active item')
|
||||
await this.selectionController.selectItem(activeItem.uuid).catch(console.error)
|
||||
} else if (this.shouldSelectFirstItem(itemsReloadSource)) {
|
||||
await this.selectFirstItem()
|
||||
@@ -547,9 +592,11 @@ export class ItemListController
|
||||
this.displayOptions = newDisplayOptions
|
||||
this.webDisplayOptions = newWebDisplayOptions
|
||||
|
||||
const newWidth = this.application.getPreference(PrefKey.NotesPanelWidth)
|
||||
if (newWidth && newWidth !== this.panelWidth) {
|
||||
this.panelWidth = newWidth
|
||||
const listColumnWidth =
|
||||
selectedTag?.preferences?.panelWidth || this.application.getPreference(PrefKey.NotesPanelWidth)
|
||||
|
||||
if (listColumnWidth && listColumnWidth !== this.panelWidth) {
|
||||
this.panelWidth = listColumnWidth
|
||||
}
|
||||
|
||||
if (!displayOptionsChanged) {
|
||||
@@ -560,7 +607,10 @@ export class ItemListController
|
||||
|
||||
await this.reloadItems(ItemsReloadSource.DisplayOptionsChange)
|
||||
|
||||
if (newDisplayOptions.sortBy !== currentSortBy) {
|
||||
if (
|
||||
newDisplayOptions.sortBy !== currentSortBy &&
|
||||
this.shouldSelectFirstItem(ItemsReloadSource.DisplayOptionsChange)
|
||||
) {
|
||||
await this.selectFirstItem()
|
||||
}
|
||||
|
||||
@@ -689,6 +739,8 @@ export class ItemListController
|
||||
const item = this.getFirstNonProtectedItem()
|
||||
|
||||
if (item) {
|
||||
log(LoggingDomain.Selection, 'Selecting first item', item.uuid)
|
||||
|
||||
await this.selectionController.selectItemWithScrollHandling(item, {
|
||||
userTriggered: false,
|
||||
scrollIntoView: false,
|
||||
@@ -702,6 +754,7 @@ export class ItemListController
|
||||
const item = this.getFirstNonProtectedItem()
|
||||
|
||||
if (item) {
|
||||
log(LoggingDomain.Selection, 'selectNextItemOrCreateNewNote')
|
||||
await this.selectionController
|
||||
.selectItemWithScrollHandling(item, {
|
||||
userTriggered: false,
|
||||
@@ -746,6 +799,7 @@ export class ItemListController
|
||||
}
|
||||
|
||||
private closeItemController(controller: NoteViewController | FileViewController): void {
|
||||
log(LoggingDomain.Selection, 'Closing item controller', controller.runtimeId)
|
||||
this.application.itemControllerGroup.closeItemController(controller)
|
||||
}
|
||||
|
||||
|
||||
@@ -431,6 +431,15 @@ export class NavigationController
|
||||
return this.selected_
|
||||
}
|
||||
|
||||
public async setPanelWidthForTag(tag: SNTag, width: number): Promise<void> {
|
||||
await this.application.mutator.changeAndSaveItem<TagMutator>(tag, (mutator) => {
|
||||
mutator.preferences = {
|
||||
...mutator.preferences,
|
||||
panelWidth: width,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
public async setSelectedTag(tag: AnyTag | undefined, { userTriggered } = { userTriggered: false }) {
|
||||
if (tag && tag.conflictOf) {
|
||||
this.application.mutator
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { ListableContentItem } from '@/Components/ContentListView/Types/ListableContentItem'
|
||||
import { log, LoggingDomain } from '@/Logging'
|
||||
import {
|
||||
ChallengeReason,
|
||||
ContentType,
|
||||
@@ -8,6 +9,7 @@ import {
|
||||
UuidString,
|
||||
InternalEventBus,
|
||||
isFile,
|
||||
Uuids,
|
||||
} from '@standardnotes/snjs'
|
||||
import { action, computed, makeObservable, observable, reaction, runInAction } from 'mobx'
|
||||
import { WebApplication } from '../Application/Application'
|
||||
@@ -248,12 +250,15 @@ export class SelectedItemsController
|
||||
didSelect: boolean
|
||||
}> => {
|
||||
const item = this.application.items.findItem<ListableContentItem>(uuid)
|
||||
|
||||
if (!item) {
|
||||
return {
|
||||
didSelect: false,
|
||||
}
|
||||
}
|
||||
|
||||
log(LoggingDomain.Selection, 'selectItem', item.uuid)
|
||||
|
||||
const hasMeta = this.io.activeModifiers.has(KeyboardModifier.Meta)
|
||||
const hasCtrl = this.io.activeModifiers.has(KeyboardModifier.Ctrl)
|
||||
const hasShift = this.io.activeModifiers.has(KeyboardModifier.Shift)
|
||||
@@ -304,14 +309,18 @@ export class SelectedItemsController
|
||||
}
|
||||
|
||||
selectUuids = async (uuids: UuidString[], userTriggered = false) => {
|
||||
const itemsForUuids = this.application.items.findItems(uuids)
|
||||
const itemsForUuids = this.application.items.findItems(uuids).filter((item) => !isFile(item))
|
||||
|
||||
if (itemsForUuids.length < 1) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!userTriggered && itemsForUuids.some((item) => item.protected && isFile(item))) {
|
||||
return
|
||||
}
|
||||
this.setSelectedUuids(new Set(uuids))
|
||||
|
||||
this.setSelectedUuids(new Set(Uuids(itemsForUuids)))
|
||||
|
||||
if (itemsForUuids.length === 1) {
|
||||
void this.openSingleSelectedItem()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user