diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 69c921e9..6d6282e7 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -24,6 +24,7 @@ jobs: - name: Build vue app run: | make dev-setup + make patch-external make build-js-production zip -r vue.zip js/ @@ -40,8 +41,8 @@ jobs: # do not stop on another job's failure fail-fast: false matrix: - php-versions: ['7.4'] - server-versions: ['stable25'] + php-versions: ["7.4"] + server-versions: ["stable25"] services: mysql: @@ -100,7 +101,6 @@ jobs: name: report-mysql-${{ matrix.php-versions }}-${{ matrix.server-versions }} path: apps/${{ env.APP_NAME }}/playwright-report - pgsql: runs-on: ubuntu-latest needs: vue @@ -109,8 +109,8 @@ jobs: # do not stop on another job's failure fail-fast: false matrix: - php-versions: ['7.4'] - server-versions: ['stable25'] + php-versions: ["7.4"] + server-versions: ["stable25"] services: postgres: @@ -181,8 +181,8 @@ jobs: # do not stop on another job's failure fail-fast: false matrix: - php-versions: ['7.4'] - server-versions: ['stable25'] + php-versions: ["7.4"] + server-versions: ["stable25"] steps: - name: Checkout server @@ -231,4 +231,3 @@ jobs: with: name: report-sqlite-${{ matrix.php-versions }}-${{ matrix.server-versions }} path: apps/${{ env.APP_NAME }}/playwright-report - diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 653f6d62..1afb512d 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -13,34 +13,35 @@ jobs: permissions: contents: write steps: - - name: Checkout - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@v3 - - name: Use Node.js - uses: actions/setup-node@v3 - with: - node-version: 18.x + - name: Use Node.js + uses: actions/setup-node@v3 + with: + node-version: 18.x - - name: Build - run: | - make dev-setup - make build-js-production - ./scripts/bundle.sh + - name: Build + run: | + make dev-setup + make patch-external + make build-js-production + ./scripts/bundle.sh - - name: Upload app tarball to release - uses: svenstaro/upload-release-action@v2 - id: attach_to_release - with: - file: memories.tar.gz - asset_name: memories.tar.gz - tag: ${{ github.ref }} - overwrite: true + - name: Upload app tarball to release + uses: svenstaro/upload-release-action@v2 + id: attach_to_release + with: + file: memories.tar.gz + asset_name: memories.tar.gz + tag: ${{ github.ref }} + overwrite: true - - name: Upload app to Nextcloud appstore - uses: R0Wi/nextcloud-appstore-push-action@v1 - with: - app_name: ${{ env.APP_NAME }} - appstore_token: ${{ secrets.APPSTORE_TOKEN }} - download_url: ${{ steps.attach_to_release.outputs.browser_download_url }} - app_private_key: ${{ secrets.APP_PRIVATE_KEY }} - nightly: ${{ github.event.release.prerelease }} \ No newline at end of file + - name: Upload app to Nextcloud appstore + uses: R0Wi/nextcloud-appstore-push-action@v1 + with: + app_name: ${{ env.APP_NAME }} + appstore_token: ${{ secrets.APPSTORE_TOKEN }} + download_url: ${{ steps.attach_to_release.outputs.browser_download_url }} + app_private_key: ${{ secrets.APP_PRIVATE_KEY }} + nightly: ${{ github.event.release.prerelease }} diff --git a/Makefile b/Makefile index b42e2cf7..8df363fa 100644 --- a/Makefile +++ b/Makefile @@ -26,6 +26,9 @@ build-js: build-js-production: rm -f js/* && npm run build +patch-external: + patch -p1 < patches/scroller.patch + watch-js: npm run watch diff --git a/package-lock.json b/package-lock.json index 08a98fe8..76abefa7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "vue-material-design-icons": "^5.1.2", "vue-property-decorator": "^9.1.2", "vue-router": "^3.5.4", - "vue-virtual-scroller": "^1.1.2", + "vue-virtual-scroller": "1.1.2", "webdav": "^4.11.0" }, "devDependencies": { diff --git a/package.json b/package.json index 3de9b1e0..335d8132 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "vue-material-design-icons": "^5.1.2", "vue-property-decorator": "^9.1.2", "vue-router": "^3.5.4", - "vue-virtual-scroller": "^1.1.2", + "vue-virtual-scroller": "1.1.2", "webdav": "^4.11.0" }, "browserslist": [ diff --git a/patches/scroller.patch b/patches/scroller.patch new file mode 100644 index 00000000..89106434 --- /dev/null +++ b/patches/scroller.patch @@ -0,0 +1,54 @@ +--- ./node_modules/vue-virtual-scroller/dist/vue-virtual-scroller.esm.js 2022-10-29 15:40:12.517184534 -0700 ++++ ./node_modules/vue-virtual-scroller/dist/vue-virtual-scroller.esm.js 2022-10-29 15:40:42.814432774 -0700 +@@ -99,6 +99,10 @@ + type: Boolean, + default: false + }, ++ updateInterval: { ++ type: Number, ++ default: 0, ++ }, + skipHover: { + type: Boolean, + default: false +@@ -262,7 +266,9 @@ + handleScroll(event) { + if (!this.$_scrollDirty) { + this.$_scrollDirty = true; +- requestAnimationFrame(() => { ++ if (this.$_updateTimeout) return ++ ++ const requestUpdate = () => requestAnimationFrame(() => { + this.$_scrollDirty = false; + const { + continuous +@@ -272,9 +278,19 @@ + // When non continous scrolling is ending, we force a refresh + if (!continuous) { + clearTimeout(this.$_refreshTimout); +- this.$_refreshTimout = setTimeout(this.handleScroll, 100); ++ this.$_refreshTimout = setTimeout(this.handleScroll, this.updateInterval + 100); + } + }); ++ ++ requestUpdate() ++ ++ // Schedule the next update with throttling ++ if (this.updateInterval) { ++ this.$_updateTimeout = setTimeout(() => { ++ this.$_updateTimeout = 0 ++ if (this.$_scrollDirty) requestUpdate(); ++ }, this.updateInterval) ++ } + } + }, + handleVisibilityChange(isVisible, entry) { +@@ -505,7 +521,7 @@ + // After the user has finished scrolling + // Sort views so text selection is correct + clearTimeout(this.$_sortTimer); +- this.$_sortTimer = setTimeout(this.sortViews, 300); ++ this.$_sortTimer = setTimeout(this.sortViews, this.updateInterval + 300); + return { + continuous + }; diff --git a/src/components/ScrollerManager.vue b/src/components/ScrollerManager.vue index 990c1362..65c0f2b8 100644 --- a/src/components/ScrollerManager.vue +++ b/src/components/ScrollerManager.vue @@ -83,9 +83,11 @@ export default class ScrollerManager extends Mixins(GlobalMixin) { /** Scrolling recycler timer */ private scrollingRecyclerTimer = null as number | null; /** View size reflow timer */ - private reflowRequest = false; + private reflowRequest!: boolean; /** Tick adjust timer */ - private adjustRequest = false; + private adjustRequest!: boolean; + /** Recycler scrolling throttle */ + private recyclerScrollDirty!: boolean; /** Get the visible ticks */ get visibleTicks() { @@ -115,6 +117,17 @@ export default class ScrollerManager extends Mixins(GlobalMixin) { /** Recycler scroll event, must be called by timeline */ public recyclerScrolled() { + if (!this.recyclerScrollDirty) { + this.recyclerScrollDirty = true; + window.setTimeout(() => { + this.recyclerScrollDirty = false; + requestAnimationFrame(this.updateFromRecyclerScroll); + }, 100); + } + } + + /** Update cursor position from recycler scroll position */ + public updateFromRecyclerScroll() { // Ignore if not initialized if (!this.ticks.length) return; @@ -556,6 +569,7 @@ export default class ScrollerManager extends Mixins(GlobalMixin) { min-width: 100%; min-height: 1.5px; will-change: transform; + transition: transform 0.1s linear; &.st { font-size: 0.75em; @@ -579,8 +593,11 @@ export default class ScrollerManager extends Mixins(GlobalMixin) { } } } - &:hover > .cursor.st { - opacity: 1; + &:hover > .cursor { + transition: none; + &.st { + opacity: 1; + } } } \ No newline at end of file diff --git a/src/components/Timeline.vue b/src/components/Timeline.vue index 33a74c89..0506d8d4 100644 --- a/src/components/Timeline.vue +++ b/src/components/Timeline.vue @@ -26,11 +26,12 @@ :class="{ empty: list.length === 0 }" :items="list" :emit-update="true" - :buffer="400" + :buffer="800" :skipHover="true" key-field="id" size-field="size" type-field="type" + :updateInterval="100" @update="scrollChange" @resize="handleResizeWithDelay" >