album: refactor picker

Signed-off-by: Varun Patil <radialapps@gmail.com>
pull/767/head
Varun Patil 2023-08-02 12:01:12 -07:00
parent 5890daba1a
commit d32793e9c0
2 changed files with 57 additions and 78 deletions

View File

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="24" height="24" fill="none"/>
<path d="M5 13.3636L8.03559 16.3204C8.42388 16.6986 9.04279 16.6986 9.43108 16.3204L19 7" stroke="#000000" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 350 B

View File

@ -13,38 +13,31 @@
albumName: album.name, albumName: album.name,
}) })
" "
@click.prevent="() => {}" @click.prevent="toggleAlbumSelection(album)"
> >
<template #icon> <template #icon>
<XImg v-if="album.last_added_photo !== -1" class="album__image" :src="toCoverUrl(album.last_added_photo)" /> <XImg v-if="album.last_added_photo !== -1" class="album__image" :src="toCoverUrl(album.last_added_photo)" />
<div v-else class="album__image album__image--placeholder"> <div v-else class="album__image album__image--placeholder">
<ImageMultiple :size="32" /> <ImageMultipleIcon :size="32" />
</div> </div>
</template> </template>
<template #subtitle> <template #subtitle>
<div @click.prevent="pickAlbum(album)"> <div>
{{ getSubtitle(album) }} {{ getSubtitle(album) }}
</div> </div>
</template> </template>
<template #extra> <template #extra>
<div <div
v-if="!selectedAlbums.has(album)"
class="check-circle-icon check-circle-icon--inactive"
@click.prevent="toggleAlbumSelection(album)"
>
<XImg :src="checkmarkIcon" />
</div>
<div
v-if="selectedAlbums.has(album)"
class="check-circle-icon" class="check-circle-icon"
@click.prevent="toggleAlbumSelection(album)" :class="{
'check-circle-icon--active': selection.has(album),
}"
> >
<XImg :src="checkmarkIcon" /> <CheckIcon :size="20" />
</div> </div>
</template> </template>
</NcListItem> </NcListItem>
</ul> </ul>
@ -56,24 +49,21 @@
@click="showAlbumCreationForm = true" @click="showAlbumCreationForm = true"
> >
<template #icon> <template #icon>
<Plus /> <PlusIcon />
</template> </template>
{{ t('memories', 'Create new album') }} {{ t('memories', 'Create new album') }}
</NcButton> </NcButton>
<div class="submit-btn-wrapper"> <div class="submit-btn-wrapper">
<NcButton <NcButton :aria-label="t('memories', 'Save')" class="new-album-button" type="primary" @click="submit">
:aria-label="t('memories', `Add to ${selectedCount} albums.`)" {{ t('memories', 'Save changes') }}
class="new-album-button"
type="primary"
@click="submit"
>
{{ t('memories', 'Add to albums') }}
</NcButton> </NcButton>
<span class="remove-notice" v-if="unselectedCount > 0"> <span class="remove-notice" v-if="deselection.size > 0">
{{ t('memories', 'And remove from') }} {{ n('memories', '{n} album', '{n} albums', unselectedCount , { {{
n: unselectedCount, n('memories', 'Removed from {n} album', 'Removed from {n} albums', deselection.size, {
})}} n: this.deselection.size,
})
}}
</span> </span>
</div> </div>
</div> </div>
@ -94,9 +84,6 @@ import { defineComponent } from 'vue';
import { getCurrentUser } from '@nextcloud/auth'; import { getCurrentUser } from '@nextcloud/auth';
import AlbumForm from './AlbumForm.vue'; import AlbumForm from './AlbumForm.vue';
import Plus from 'vue-material-design-icons/Plus.vue';
import ImageMultiple from 'vue-material-design-icons/ImageMultiple.vue';
import checkmarkIcon from '../../assets/checkmark.svg';
import axios from '@nextcloud/axios'; import axios from '@nextcloud/axios';
@ -108,6 +95,10 @@ import { IAlbum, IPhoto } from '../../types';
import { API } from '../../services/API'; import { API } from '../../services/API';
import { PropType } from 'vue'; import { PropType } from 'vue';
import PlusIcon from 'vue-material-design-icons/Plus.vue';
import ImageMultipleIcon from 'vue-material-design-icons/ImageMultiple.vue';
import CheckIcon from 'vue-material-design-icons/Check.vue';
export default defineComponent({ export default defineComponent({
name: 'AlbumPicker', name: 'AlbumPicker',
props: { props: {
@ -119,29 +110,26 @@ export default defineComponent({
}, },
components: { components: {
AlbumForm, AlbumForm,
Plus,
ImageMultiple,
NcButton, NcButton,
NcListItem, NcListItem,
PlusIcon,
ImageMultipleIcon,
CheckIcon,
}, },
data: () => ({ data: () => ({
showAlbumCreationForm: false, showAlbumCreationForm: false,
albums: [] as IAlbum[],
loadingAlbums: true, loadingAlbums: true,
photoId: -1, /** List of all albums */
checkmarkIcon, albums: [] as IAlbum[],
selectedAlbums: new Set<IAlbum>(), /** All selected albums */
unselectedAlbums: new Set<IAlbum>(), selection: new Set<IAlbum>(),
selectedCount: 0, /** Deselected albums that were previously selected */
unselectedCount: 0, deselection: new Set<IAlbum>(),
}), }),
mounted() { mounted() {
if (this.photos.length === 1) {
// this only makes sense when we try to add single photo to albums
this.photoId = this.photos[0].fileid;
}
this.loadAlbums(); this.loadAlbums();
}, },
@ -176,11 +164,14 @@ export default defineComponent({
async loadAlbums() { async loadAlbums() {
try { try {
const res = await axios.get<IAlbum[]>(API.ALBUM_LIST(3, this.photoId)); // this only makes sense when we try to add single photo to albums
const photoId = this.photos.length === 1 ? this.photos[0].fileid : -1;
// get albums, possibly for one photo
const res = await axios.get<IAlbum[]>(API.ALBUM_LIST(3, photoId));
this.albums = res.data; this.albums = res.data;
this.selectedAlbums = new Set(this.albums.filter(album => album.has_file)); this.selection = new Set(this.albums.filter((album) => album.has_file));
this.unselectedAlbums = new Set(); this.deselection = new Set();
this.unselectedCount = 0;
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} finally { } finally {
@ -189,32 +180,24 @@ export default defineComponent({
}, },
toggleAlbumSelection(album: IAlbum) { toggleAlbumSelection(album: IAlbum) {
if (this.selectedAlbums.has(album)) { if (this.selection.has(album)) {
this.selectedAlbums.delete(album); this.selection.delete(album);
this.unselectedAlbums.add(album)
} else if (this.unselectedAlbums.has(album)) { // deselection only if originally selected
this.selectedAlbums.add(album) if (album.has_file) {
this.unselectedAlbums.delete(album); this.deselection.add(album);
}
} else { } else {
this.selectedAlbums.add(album) this.selection.add(album);
this.deselection.delete(album);
} }
this.unselectedCount = this.albums.reduce((acc, album) => { this.$forceUpdate(); // sets do not trigger reactivity
if (album.has_file && this.unselectedAlbums.has(album)) {
acc += 1;
}
return acc;
}, 0); this.selectedAlbums.size;
this.selectedCount = this.selectedAlbums.size;
},
pickAlbum(album: IAlbum) {
this.$emit('select', [album], []);
}, },
submit() { submit() {
this.$emit('select', Array.from(this.selectedAlbums), Array.from(this.unselectedAlbums)); this.$emit('select', Array.from(this.selection), Array.from(this.deselection));
} },
}, },
}); });
</script> </script>
@ -276,17 +259,18 @@ export default defineComponent({
.check-circle-icon { .check-circle-icon {
border-radius: 50%; border-radius: 50%;
border: 1px solid rgba(0, 255, 0, 0.1882352941); border: 1px solid rgba($color: black, $alpha: 0.1);
background-color: rgba(0, 255, 0, 0.1882352941); background-color: transparent;
height: 34px; height: 34px;
width: 34px; width: 34px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
&--inactive { &--active {
border: 1px solid rgba($color: black, $alpha: 0.1); border: 1px solid var(--color-primary);
background-color: transparent; background-color: var(--color-primary-default);
color: var(--color-primary-text);
} }
& img { & img {