From d940aa573e691a13752983575f67d2fe42575fb6 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Sun, 6 Nov 2022 00:03:01 -0700 Subject: [PATCH 1/7] Update tests --- e2e/folders.spec.ts | 20 +++++++++++--------- e2e/login.ts | 22 ++++++++++++---------- e2e/timeline.spec.ts | 38 +++++++++++++++++++++++++------------- 3 files changed, 48 insertions(+), 32 deletions(-) diff --git a/e2e/folders.spec.ts b/e2e/folders.spec.ts index c6ac18a7a..dd33a7600 100644 --- a/e2e/folders.spec.ts +++ b/e2e/folders.spec.ts @@ -1,15 +1,17 @@ -import { test, expect } from '@playwright/test'; -import { login } from './login'; +import { test, expect } from "@playwright/test"; +import { login } from "./login"; -test.beforeEach(login('/folders')); +test.beforeEach(login("/folders")); -test.describe('Open', () => { - test('Look for Folders', async ({ page }) => { - expect(await page.locator('.big-icon').count(), 'Number of folders').toBe(2); +test.describe("Open", () => { + test("Look for Folders", async ({ page }) => { + expect(await page.locator(".big-icon").count(), "Number of folders").toBe( + 2 + ); }); - test('Open folder', async ({ page }) => { - await page.locator('text=Local').click(); + test("Open folder", async ({ page }) => { + await page.locator("text=Local").click(); await page.waitForSelector('img[src*="core/preview"]'); }); -}); \ No newline at end of file +}); diff --git a/e2e/login.ts b/e2e/login.ts index 137796320..2278626d6 100644 --- a/e2e/login.ts +++ b/e2e/login.ts @@ -1,16 +1,18 @@ -import { expect, PlaywrightTestArgs } from '@playwright/test'; +import { expect, PlaywrightTestArgs } from "@playwright/test"; export function login(route: string) { return async ({ page }: PlaywrightTestArgs) => { - await page.setViewportSize({ width: 800, height: 600 }) - await page.goto('http://localhost:8080/index.php/apps/memories' + route) + await page.setViewportSize({ width: 800, height: 600 }); + await page.goto("http://localhost:8080/index.php/apps/memories" + route); - await page.locator('#user').click(); - await page.locator('#user').fill('admin'); - await page.locator('#user').press('Tab'); - await page.locator('#password').fill('password'); + await page.locator("#user").click(); + await page.locator("#user").fill("admin"); + await page.locator("#user").press("Tab"); + await page.locator("#password").fill("password"); await page.locator('button[type="submit"]').click(); - await expect(page).toHaveURL('http://localhost:8080/index.php/apps/memories' + route); + await expect(page).toHaveURL( + "http://localhost:8080/index.php/apps/memories" + route + ); await page.waitForSelector('img[src*="core/preview"]'); - } -} \ No newline at end of file + }; +} diff --git a/e2e/timeline.spec.ts b/e2e/timeline.spec.ts index 59cfc98a1..06430ae77 100644 --- a/e2e/timeline.spec.ts +++ b/e2e/timeline.spec.ts @@ -1,26 +1,38 @@ -import { test, expect } from '@playwright/test'; -import { login } from './login'; +import { test, expect } from "@playwright/test"; +import { login } from "./login"; -test.beforeEach(login('/')); +test.beforeEach(login("/")); -test.describe('Open', () => { - test('Look for Images', async ({ page }) => { - expect(await page.locator('img[src*="core/preview"]').count(), 'Number of previews').toBeGreaterThan(4); +test.describe("Open", () => { + test("Look for Images", async ({ page }) => { + expect( + await page.locator('img[src*="core/preview"]').count(), + "Number of previews" + ).toBeGreaterThan(4); await page.waitForTimeout(1000); }); - test('Open one image', async ({ page }) => { - await page.locator('div:nth-child(2) > .p-outer > .img-outer > img').first().click(); + test("Open one image", async ({ page }) => { + await page + .locator("div:nth-child(2) > .p-outer > .img-outer > img") + .first() + .click(); await page.waitForTimeout(1000); - await page.locator('button.header-close').first().click(); + await page.locator('button[title="Close"]').first().click(); }); - test('Select two images and delete', async ({ page }) => { + test("Select two images and delete", async ({ page }) => { const i1 = "div:nth-child(2) > div:nth-child(1) > .p-outer"; const i2 = "div:nth-child(2) > div:nth-child(2) > .p-outer"; - const src1 = await page.locator(`${i1} > .img-outer > img`).first().getAttribute('src'); - const src2 = await page.locator(`${i2} > .img-outer > img`).first().getAttribute('src'); + const src1 = await page + .locator(`${i1} > .img-outer > img`) + .first() + .getAttribute("src"); + const src2 = await page + .locator(`${i2} > .img-outer > img`) + .first() + .getAttribute("src"); expect(await page.locator(`img[src="${src1}"]`).count()).toBe(1); expect(await page.locator(`img[src="${src2}"]`).count()).toBe(1); @@ -42,4 +54,4 @@ test.describe('Open', () => { expect(await page.locator(`img[src="${src1}"]`).count()).toBe(0); expect(await page.locator(`img[src="${src2}"]`).count()).toBe(0); }); -}); \ No newline at end of file +}); From db7695476c0cd142b411a28ef4301bcb5e6e6fbd Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Sun, 6 Nov 2022 00:05:28 -0700 Subject: [PATCH 2/7] actions/upload-artifact v3 --- .github/workflows/e2e.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 6d6282e7e..4309147a5 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -28,7 +28,7 @@ jobs: make build-js-production zip -r vue.zip js/ - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: vue.zip path: vue.zip From ccfa9520dd5b7e572ffc0909979c56e0ff3299f2 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Sun, 6 Nov 2022 00:10:21 -0700 Subject: [PATCH 3/7] l10n: fix wrong syntax (fix #161) --- src/components/modal/AlbumForm.vue | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/components/modal/AlbumForm.vue b/src/components/modal/AlbumForm.vue index ca307cdd7..cb5b90091 100644 --- a/src/components/modal/AlbumForm.vue +++ b/src/components/modal/AlbumForm.vue @@ -69,9 +69,7 @@ {{ t("photos", "Add collaborators") }} - {{ editMode ? t("photos", "Save") : t("photos", "Create album") }} + {{ saveText }} @@ -103,9 +101,7 @@ - {{ editMode ? t("photos", "Save") : t("photos", "Create album") }} + {{ saveText }} @@ -162,6 +158,12 @@ export default class AlbumForm extends Mixins(GlobalMixin) { return Boolean(this.album); } + get saveText(): string { + return this.editMode + ? this.t("photos", "Save") + : this.t("photos", "Create album"); + } + /** * @return Whether sharing is enabled. */ From 3e0231bfad368d1838d0c55090bbaa0f6a55fef7 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Sun, 6 Nov 2022 00:28:32 -0700 Subject: [PATCH 4/7] viewer: fix folder share --- src/components/Viewer.vue | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/components/Viewer.vue b/src/components/Viewer.vue index b3272c2b8..1fca297e7 100644 --- a/src/components/Viewer.vue +++ b/src/components/Viewer.vue @@ -213,7 +213,7 @@ export default class Viewer extends Mixins(GlobalMixin) { const klass = "has-viewer"; this.photoswipe.on("beforeOpen", () => { document.body.classList.add(klass); - navElem.style.zIndex = "0"; + if (navElem) navElem.style.zIndex = "0"; }); this.photoswipe.on("openingAnimationStart", () => { this.fullyOpened = false; @@ -230,12 +230,9 @@ export default class Viewer extends Mixins(GlobalMixin) { this.opened = false; this.hideSidebar(); }); - this.photoswipe.on("tapAction", () => { - this.opened = !this.opened; // toggle-controls - }); this.photoswipe.on("destroy", () => { document.body.classList.remove(klass); - navElem.style.zIndex = ""; + if (navElem) navElem.style.zIndex = ""; // reset everything this.show = false; @@ -249,6 +246,11 @@ export default class Viewer extends Mixins(GlobalMixin) { this.globalAnchor = -1; }); + // toggle-controls + this.photoswipe.on("tapAction", () => { + this.opened = !this.opened; + }); + // Video support this.photoswipe.on("contentLoad", (e) => { const { content, isLazy } = e; From 4d9c301f269105e5a4ec3edf73589aa22524f9e5 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Sun, 6 Nov 2022 00:28:40 -0700 Subject: [PATCH 5/7] folder-share: fix download --- src/services/dav/download.ts | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/services/dav/download.ts b/src/services/dav/download.ts index 6d153566f..81703d93b 100644 --- a/src/services/dav/download.ts +++ b/src/services/dav/download.ts @@ -16,7 +16,7 @@ export async function downloadFiles(fileNames: string[]): Promise { params.append("files", JSON.stringify(fileNames)); params.append("downloadStartSecret", randomToken); - const downloadURL = generateUrl(`/apps/files/ajax/download.php?${params}`); + let downloadURL = generateUrl(`/apps/files/ajax/download.php?${params}`); window.location.href = `${downloadURL}downloadStartSecret=${randomToken}`; @@ -38,6 +38,27 @@ export async function downloadFiles(fileNames: string[]): Promise { }); } +/** + * Download public photo + * @param photo - The photo to download + */ +export async function downloadPublicPhoto(photo: IPhoto) { + // Public share download + + const token = window.vuerouter.currentRoute.params.token; + // TODO: allow proper dav access without the need of basic auth + // https://github.com/nextcloud/server/issues/19700 + const downloadURL = generateUrl( + `/s/${token}/download?path={dirname}&files={basename}`, + { + dirname: photo.filename.split("/").slice(0, -1).join("/"), + basename: photo.basename, + } + ); + + window.location.href = downloadURL; +} + /** * Download the files given by the fileIds * @param photos list of photos @@ -47,6 +68,14 @@ export async function downloadFilesByIds(photos: IPhoto[]) { return; } + // Public files + if (vuerouter.currentRoute.name === "folder-share") { + for (const photo of photos) { + await downloadPublicPhoto(photo); + } + return; + } + // Get files to download const fileInfos = await base.getFiles(photos); if (fileInfos.length !== photos.length) { From 3e854719eda4ed7f8af2f7391e566e454c44510f Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Sun, 6 Nov 2022 00:36:35 -0700 Subject: [PATCH 6/7] viewer: fix folder-share video --- src/components/SelectionManager.vue | 2 +- src/components/Viewer.vue | 18 ++--------- src/services/dav/download.ts | 47 ++++++++++++++++++++--------- 3 files changed, 36 insertions(+), 31 deletions(-) diff --git a/src/components/SelectionManager.vue b/src/components/SelectionManager.vue index cf6dfa992..81574279a 100644 --- a/src/components/SelectionManager.vue +++ b/src/components/SelectionManager.vue @@ -348,7 +348,7 @@ export default class SelectionManager extends Mixins(GlobalMixin, UserConfig) { return; } } - await dav.downloadFilesByIds(Array.from(selection.values())); + await dav.downloadFilesByPhotos(Array.from(selection.values())); } /** diff --git a/src/components/Viewer.vue b/src/components/Viewer.vue index 1fca297e7..593406819 100644 --- a/src/components/Viewer.vue +++ b/src/components/Viewer.vue @@ -76,7 +76,7 @@ import { generateUrl } from "@nextcloud/router"; import * as dav from "../services/DavRequests"; import * as utils from "../services/Utils"; import { getPreviewUrl } from "../services/FileUtils"; -import { getAlbumFileInfos } from "../services/DavRequests"; +import { getDownloadLink } from "../services/DavRequests"; import PhotoSwipe, { PhotoSwipeOptions } from "photoswipe"; import "photoswipe/style.css"; @@ -264,19 +264,7 @@ export default class Viewer extends Mixins(GlobalMixin) { content.videoElement.classList.add("video-js"); // Get DAV URL for video - let url = `remote.php/dav/${content.data.photo.filename}`; // normal route - // Check if albums - const route = vuerouter.currentRoute; - if (route.name === "albums") { - const fInfos = getAlbumFileInfos( - [content.data.photo], - route.params.user, - route.params.name - ); - if (fInfos.length) { - url = `remote.php/dav/${fInfos[0].originalFilename}`; - } - } + const url = getDownloadLink(content.data.photo); // Add child with source element const source = document.createElement("source"); @@ -525,7 +513,7 @@ export default class Viewer extends Mixins(GlobalMixin) { private async downloadCurrent() { const photo = this.getCurrentPhoto(); if (!photo) return; - dav.downloadFilesByIds([photo]); + dav.downloadFilesByPhotos([photo]); } /** Open the sidebar */ diff --git a/src/services/dav/download.ts b/src/services/dav/download.ts index 81703d93b..c24eba556 100644 --- a/src/services/dav/download.ts +++ b/src/services/dav/download.ts @@ -3,6 +3,7 @@ import { generateUrl } from "@nextcloud/router"; import { showError } from "@nextcloud/dialogs"; import { translate as t } from "@nextcloud/l10n"; import { IPhoto } from "../../types"; +import { getAlbumFileInfos } from "./albums"; /** * Download a file @@ -43,27 +44,14 @@ export async function downloadFiles(fileNames: string[]): Promise { * @param photo - The photo to download */ export async function downloadPublicPhoto(photo: IPhoto) { - // Public share download - - const token = window.vuerouter.currentRoute.params.token; - // TODO: allow proper dav access without the need of basic auth - // https://github.com/nextcloud/server/issues/19700 - const downloadURL = generateUrl( - `/s/${token}/download?path={dirname}&files={basename}`, - { - dirname: photo.filename.split("/").slice(0, -1).join("/"), - basename: photo.basename, - } - ); - - window.location.href = downloadURL; + window.location.href = getDownloadLink(photo); } /** * Download the files given by the fileIds * @param photos list of photos */ -export async function downloadFilesByIds(photos: IPhoto[]) { +export async function downloadFilesByPhotos(photos: IPhoto[]) { if (photos.length === 0) { return; } @@ -87,3 +75,32 @@ export async function downloadFilesByIds(photos: IPhoto[]) { await downloadFiles(fileInfos.map((f) => f.filename)); } + +/** Get URL to download one file (e.g. for video streaming) */ +export function getDownloadLink(photo: IPhoto) { + // Check if public + if (vuerouter.currentRoute.name === "folder-share") { + const token = window.vuerouter.currentRoute.params.token; + // TODO: allow proper dav access without the need of basic auth + // https://github.com/nextcloud/server/issues/19700 + return generateUrl(`/s/${token}/download?path={dirname}&files={basename}`, { + dirname: photo.filename.split("/").slice(0, -1).join("/"), + basename: photo.basename, + }); + } + + // Check if albums + const route = vuerouter.currentRoute; + if (route.name === "albums") { + const fInfos = getAlbumFileInfos( + [photo], + route.params.user, + route.params.name + ); + if (fInfos.length) { + return `remote.php/dav/${fInfos[0].originalFilename}`; + } + } + + return `remote.php/dav/${photo.filename}`; // normal route +} From 8341f6fd06d86db6b041530b0f76ba2cf0cb2e87 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Sun, 6 Nov 2022 00:40:57 -0700 Subject: [PATCH 7/7] viewer: fix for tagdayid --- src/components/Viewer.vue | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/Viewer.vue b/src/components/Viewer.vue index 593406819..0dbc6f439 100644 --- a/src/components/Viewer.vue +++ b/src/components/Viewer.vue @@ -320,6 +320,8 @@ export default class Viewer extends Mixins(GlobalMixin) { for (const r of rows) { if (r.type === IRowType.HEAD) { + if (this.TagDayIDValueSet.has(r.dayId)) continue; + if (r.day.dayid == anchorPhoto.d.dayid) { startIndex = r.day.detail.findIndex( (p) => p.fileid === anchorPhoto.fileid