Merge branch 'master' into stable24

old_stable24
Varun Patil 2022-11-06 00:41:10 -07:00
commit 04bad3d020
8 changed files with 120 additions and 64 deletions

View File

@ -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

View File

@ -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"]');
});
});
});

View File

@ -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"]');
}
}
};
}

View File

@ -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);
});
});
});

View File

@ -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()));
}
/**

View File

@ -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";
@ -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;
@ -262,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");
@ -330,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
@ -523,7 +515,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 */

View File

@ -69,9 +69,7 @@
{{ t("photos", "Add collaborators") }}
</NcButton>
<NcButton
:aria-label="
editMode ? t('photos', 'Save.') : t('photos', 'Create the album.')
"
:aria-label="saveText"
type="primary"
:disabled="albumName === '' || loading"
@click="submit()"
@ -80,7 +78,7 @@
<NcLoadingIcon v-if="loading" />
<Send v-else />
</template>
{{ editMode ? t("photos", "Save") : t("photos", "Create album") }}
{{ saveText }}
</NcButton>
</span>
</div>
@ -103,9 +101,7 @@
</span>
<span class="right-buttons">
<NcButton
:aria-label="
editMode ? t('photos', 'Save.') : t('photos', 'Create the album.')
"
:aria-label="saveText"
type="primary"
:disabled="albumName.trim() === '' || loading"
@click="submit(collaborators)"
@ -114,7 +110,7 @@
<NcLoadingIcon v-if="loading" />
<Send v-else />
</template>
{{ editMode ? t("photos", "Save") : t("photos", "Create album") }}
{{ saveText }}
</NcButton>
</span>
</template>
@ -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.
*/

View File

@ -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
@ -16,7 +17,7 @@ export async function downloadFiles(fileNames: string[]): Promise<boolean> {
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,15 +39,31 @@ export async function downloadFiles(fileNames: string[]): Promise<boolean> {
});
}
/**
* Download public photo
* @param photo - The photo to download
*/
export async function downloadPublicPhoto(photo: IPhoto) {
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;
}
// 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) {
@ -58,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
}