diff --git a/CHANGELOG.md b/CHANGELOG.md index 251c668351..b1f547e7b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ You can also check [on GitHub](https://github.com/nextcloud/news/releases), the ### Changed - added alternative development environment (#2670) - Implement `j` and `k` keyboards shortcuts for navigating through feed items (#2671) +- Implement `s`, `i` and `l` keyboards shortcuts for staring current feed item (#2677) +- Implement `o` keyboards shortcut for opening the URL of current feed item (#2677) +- Implement `u` keyboards shortcut for marking current feed item read/unread (#2677) +- Implement highlighting of active feed item (#2677) ### Fixed diff --git a/Makefile b/Makefile index ece7d07f11..fd3b254d81 100644 --- a/Makefile +++ b/Makefile @@ -229,7 +229,7 @@ nextcloud-server: .PHONY: term term: - zellij --layout term.kdl attach nextcloud-news -c + zellij --layout term.kdl attach nextcloud-news -cf .PHONY: term-kill term-kill: diff --git a/src/components/feed-display/FeedItemDisplay.vue b/src/components/feed-display/FeedItemDisplay.vue index 0831214212..bc5fd4ad25 100644 --- a/src/components/feed-display/FeedItemDisplay.vue +++ b/src/components/feed-display/FeedItemDisplay.vue @@ -12,7 +12,12 @@ + + +
- @@ -74,7 +78,7 @@ const DEFAULT_DISPLAY_LIST_CONFIG = { export type Config = { unreadFilter: boolean; - starFlter: boolean; + starFilter: boolean; } export default Vue.extend({ @@ -121,6 +125,7 @@ export default Vue.extend({ } }, cache: [] as FeedItem[] | undefined, + selectedItem: undefined as FeedItem | undefined, } }, computed: { @@ -130,10 +135,15 @@ export default Vue.extend({ cfg() { return _.defaults({ ...this.config }, DEFAULT_DISPLAY_LIST_CONFIG) }, - selectedItem() { + getSelectedItem() { return this.$store.getters.selected }, }, + watch: { + getSelectedItem(newVal) { + this.selectedItem = newVal + }, + }, mounted() { this.mounted = true }, @@ -185,7 +195,7 @@ export default Vue.extend({ return response.sort(this.sort) }, // Trigger the click event programmatically to benefit from the item handling inside the FeedItemRow component - clickItem(item: FeedItem) { + clickItem(item: FeedItem, alignToTop = false) { const refName = 'feedItemRow' + item.id const ref = this.$refs[refName] // Make linter happy @@ -194,21 +204,17 @@ export default Vue.extend({ if (element) { element.click() - - // TODO: This doesn't seem to do a lot in the VirtualScroll component - element.scrollIntoView(true) - // this.$nextTick(() => element.scrollIntoView()) + const virtualScroll = this.$refs.virtualScroll + // TODO: This is still jerky and even can derail the current item + // virtualScroll.showElement(element, alignToTop) } }, currentIndex(items: FeedItem[]): number { return this.selectedItem ? items.findIndex((item: FeedItem) => item.id === this.selectedItem.id) || 0 : -1 }, - // TODO: Make jumpToPreviousItem() highlight the current item jumpToPreviousItem() { - console.log('Previous item') const items = this.filterSortedItems() let currentIndex = this.currentIndex(items) - console.log('currentIndex', currentIndex) // Prepare to jump to the first item, if none was selected if (currentIndex === -1) { currentIndex = 1 @@ -216,21 +222,16 @@ export default Vue.extend({ // Jump to the previous item if (currentIndex > 0) { const previousItem = items[currentIndex - 1] - console.log('previousItem', previousItem) - this.clickItem(previousItem) + this.clickItem(previousItem, true) } }, - // TODO: Make jumpToNextItem() highlight the current item jumpToNextItem() { - console.log('Next item') const items = this.filterSortedItems() const currentIndex = this.currentIndex(items) - console.log('currentIndex', currentIndex) // Jump to the first item, if none was selected, otherwise jump to the next item if (currentIndex === -1 || (currentIndex < items.length - 1)) { const nextItem = items[currentIndex + 1] - console.log('nextItem', nextItem) - this.clickItem(nextItem) + this.clickItem(nextItem, false) } }, }, diff --git a/src/components/feed-display/FeedItemRow.vue b/src/components/feed-display/FeedItemRow.vue index baa9e78edd..b7e9b86929 100644 --- a/src/components/feed-display/FeedItemRow.vue +++ b/src/components/feed-display/FeedItemRow.vue @@ -276,4 +276,8 @@ export default Vue.extend({ .feed-item-row .button-container .eye-check-icon { color: var(--color-placeholder-dark); } + + .active, .active:hover { + background-color: var(--color-background-darker); + } diff --git a/src/components/feed-display/VirtualScroll.vue b/src/components/feed-display/VirtualScroll.vue index c6bb471bd9..160be18eeb 100644 --- a/src/components/feed-display/VirtualScroll.vue +++ b/src/components/feed-display/VirtualScroll.vue @@ -31,6 +31,7 @@ export default Vue.extend({ scrollHeight: 500, initialLoadingSkeleton: false, initialLoadingTimeout: null, + elementToShow: null, } }, computed: { @@ -38,6 +39,9 @@ export default Vue.extend({ return this.$store.state.items.fetchingItems[this.key] }, }, + created() { + this.elementToShowAlignToTop = false + }, watch: { newBookmark() { this.$el.scrollTop = 0 @@ -58,6 +62,10 @@ export default Vue.extend({ this.scrollTop = this.$el.scrollTop this.scrollHeight = this.$el.scrollHeight }, + showElement(element, alignToTop) { + this.elementToShow = element + this.elementToShowAlignToTop = alignToTop + }, }, render(h) { let children = [] @@ -106,7 +114,13 @@ export default Vue.extend({ const scrollTop = this.scrollTop this.$nextTick(() => { - this.$el.scrollTop = scrollTop + if (this.elementToShow) { + // this.elementToShow.scrollIntoView(this.elementToShowAlignToTop) + this.elementToShow.scrollIntoView({ behavior: 'smooth', block: 'center' }) + this.elementToShow = null + } else { + this.$el.scrollTop = scrollTop + } }) return h('div', { diff --git a/src/types/FeedItem.ts b/src/types/FeedItem.ts index 879a663f4d..979f4bfcb8 100644 --- a/src/types/FeedItem.ts +++ b/src/types/FeedItem.ts @@ -6,4 +6,5 @@ export type FeedItem = { feedId: number; guidHash: string; pubDate: number; + url: string; };