Implement selecting and favorite (fix #26)
parent
bee28095fa
commit
bdc964d2ee
|
@ -102,6 +102,14 @@
|
|||
{{ t('memories', 'Delete') }}
|
||||
</NcActionButton>
|
||||
</NcActions>
|
||||
<NcActions>
|
||||
<NcActionButton
|
||||
:aria-label="t('memories', 'Toggle Favorite')"
|
||||
@click="favoriteSelection"
|
||||
class="icon-favorite">
|
||||
{{ t('memories', 'Toggle Favorite') }}
|
||||
</NcActionButton>
|
||||
</NcActions>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -932,6 +940,38 @@ export default class Timeline extends Mixins(GlobalMixin) {
|
|||
}
|
||||
await dav.downloadFilesByIds(Array.from(this.selection.keys()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if all files selected currently are favorites
|
||||
*/
|
||||
allSelectedFavorites() {
|
||||
return Array.from(this.selection.values()).every(p => p.flag & this.c.FLAG_IS_FAVORITE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Favorite the currently selected photos
|
||||
*/
|
||||
async favoriteSelection() {
|
||||
try {
|
||||
const val = !this.allSelectedFavorites();
|
||||
this.loading++;
|
||||
for await (const favIds of dav.favoriteFilesByIds(Array.from(this.selection.keys()), val)) {
|
||||
favIds.forEach(id => {
|
||||
const photo = this.selection.get(id);
|
||||
if (!photo) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (val) {
|
||||
photo.flag |= this.c.FLAG_IS_FAVORITE;
|
||||
} else {
|
||||
photo.flag &= ~this.c.FLAG_IS_FAVORITE;
|
||||
}
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
this.loading--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -265,3 +265,69 @@ export async function downloadFilesByIds(fileIds: number[]) {
|
|||
const fileInfos = await getFiles(fileIds);
|
||||
await downloadFiles(fileInfos.map(f => f.filename));
|
||||
}
|
||||
|
||||
/**
|
||||
* Favorite a file
|
||||
* https://github.com/nextcloud/photos/blob/7687e214f9b0f71a2cc73778b8b22ab781490a3b/src/services/FileActions.js
|
||||
*
|
||||
* @param fileName - The file's name
|
||||
* @param favoriteState - The new favorite state
|
||||
*/
|
||||
export async function favoriteFile(fileName: string, favoriteState: boolean) {
|
||||
let encodedPath = encodePath(fileName)
|
||||
while (encodedPath[0] === '/') {
|
||||
encodedPath = encodedPath.substring(1)
|
||||
}
|
||||
|
||||
try {
|
||||
return axios.post(
|
||||
`${generateUrl('/apps/files/api/v1/files/')}${encodedPath}`,
|
||||
{
|
||||
tags: favoriteState ? ['_$!<Favorite>!$_'] : [],
|
||||
},
|
||||
)
|
||||
} catch (error) {
|
||||
console.error(t('memories', 'Failed to favorite {fileName}.', { fileName }), error)
|
||||
showError(t('memories', 'Failed to favorite {fileName}.', { fileName }))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Favorite all files in a given list of Ids
|
||||
*
|
||||
* @param fileIds list of file ids
|
||||
* @param favoriteState the new favorite state
|
||||
* @returns generator of lists of file ids that were state-changed
|
||||
*/
|
||||
export async function* favoriteFilesByIds(fileIds: number[], favoriteState: boolean) {
|
||||
const fileIdsSet = new Set(fileIds);
|
||||
|
||||
if (fileIds.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get files data
|
||||
let fileInfos: any[] = [];
|
||||
try {
|
||||
fileInfos = await getFiles(fileIds.filter(f => f));
|
||||
} catch (e) {
|
||||
showError(t('memories', 'Failed to favorite files.'));
|
||||
console.error('Failed to get file info for files to favorite', fileIds, e);
|
||||
return;
|
||||
}
|
||||
|
||||
// Favorite each file
|
||||
fileInfos = fileInfos.filter((f) => fileIdsSet.has(f.fileid));
|
||||
const calls = fileInfos.map((fileInfo) => async () => {
|
||||
try {
|
||||
await favoriteFile(fileInfo.filename, favoriteState);
|
||||
return fileInfo.fileid as number;
|
||||
} catch (error) {
|
||||
console.error(t('memories', 'Failed to favorite {fileName}.', fileInfo), error);
|
||||
showError(t('memories', 'Failed to favorite {fileName}.', fileInfo));
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
yield* runInParallel(calls, 10);
|
||||
}
|
Loading…
Reference in New Issue