Skip to content

Commit

Permalink
fix(галерея): #10
Browse files Browse the repository at this point in the history
Эти изменения не решают проблему полностью, но конкретно для листания вперёд зацикливания не будет (назад будет). Плюсом: уменьшено время открытия фото.
  • Loading branch information
ivanmem committed Oct 16, 2023
1 parent 1abc475 commit cb5219d
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 90 deletions.
4 changes: 2 additions & 2 deletions src/helpers/GroupHelper.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { IGroup } from "@/store/groups/types";
import { GroupState, IGroup } from "@/store/groups/types";
import {
FiltersType,
GroupsSortEnum,
groupsSortKeys,
OnlyAccessEnum,
useGroups,
} from "@/store/groups/groups";
import { getGroupState, GroupState } from "@/pages/AGroups/getGroupState";
import { getGroupState } from "@/pages/AGroups/getGroupState";
import bridge from "@vkontakte/vk-bridge";
import { from, IEnumerable, NumberComparer } from "linq-to-typescript";

Expand Down
22 changes: 20 additions & 2 deletions src/helpers/PhotoHelper.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { IPhoto, IPhotoSize } from "vkontakte-api";
import { IPhotoSize } from "vkontakte-api";
import last from "lodash/last";
import isNumeric from "@/helpers/isNumeric";
import { VK_MAX_PHOTO_SIZE } from "@/common/consts";
import { ComputedRef } from "vue";
import { IPhoto, IPhotoKey } from "@/store/groups/types";

export class PhotoHelper {
static getOriginalSize(sizes: IPhotoSize[] | undefined) {
Expand Down Expand Up @@ -59,10 +60,27 @@ export class PhotoHelper {
return `vk.com/id${ownerId}`;
}

static getPhotoUrl(ownerId: number | string, photoId: number) {
static getPhotoUrl(ownerId: number | string, photoId: number | string) {
return `vk.com/photo${ownerId}_${photoId}`;
}

static getPhotoKey(
ownerId: number | string,
photoId: number | string,
): IPhotoKey {
return `photo${ownerId}_${photoId}`;
}

static getPhotoKeyOrUndefined(
ownerId: number | string | undefined,
photoId: number | string | undefined,
): IPhotoKey | undefined {
if (ownerId === undefined || photoId === undefined) {
return undefined;
}
return this.getPhotoKey(ownerId, photoId);
}

static getPhotoFileName(photo: IPhoto) {
return `photo${photo.owner_id}_${photo.id}.jpg`;
}
Expand Down
2 changes: 1 addition & 1 deletion src/pages/AAlbum/AAlbumPreview.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<script lang="ts" setup>
import { IPhoto } from "vkontakte-api";
import { computed, h, toRefs } from "vue";
import { PhotoHelper } from "@/helpers/PhotoHelper";
import { showContextMenu } from "@/helpers/showContextMenu";
import { icons } from "@/common/consts";
import { openLink } from "@/helpers/openLink";
import { saveAs } from "file-saver";
import { AlbumsPreviewSizes } from "@/pages/AAlbums/consts";
import { IPhoto } from "@/store/groups/types";
const props = defineProps<{ photo: IPhoto }>();
const originalSize = computed(() =>
Expand Down
78 changes: 58 additions & 20 deletions src/pages/AAlbum/useAlbum.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
import { IAlbumItem, PhotosGetAlbums } from "@/store/vk/IAlbumItem";
import { useVk } from "@/store/vk/vk";
import { toString } from "lodash";
import { AlbumsPreviewSizes, AlbumsPreviewSizesInitial, getStaticAlbums } from "@/pages/AAlbums/consts";
import { computed, MaybeRefOrGetter, nextTick, ref, toRefs, toValue, watch } from "vue";
import { IPhoto } from "vkontakte-api";
import {
AlbumsPreviewSizes,
AlbumsPreviewSizesInitial,
getStaticAlbums,
} from "@/pages/AAlbums/consts";
import {
computed,
MaybeRefOrGetter,
nextTick,
ref,
toRefs,
toValue,
watch,
} from "vue";
import { useCurrentPhoto } from "@/pages/AAlbum/useCurrentPhoto";
import { useScreenSpinner } from "@/composables/useScreenSpinner";
import { useCountGridColumns } from "@/composables/useCountGridColumns";
Expand All @@ -12,6 +23,8 @@ import { toStr } from "@/helpers/toStr";
import { useGroups } from "@/store/groups/groups";
import { useHistory } from "@/store/history/history";
import { toNumberOrUndefined } from "@/helpers/toNumberOrUndefined";
import { IPhoto, IPhotoKey } from "@/store/groups/types";
import { PhotoHelper } from "@/helpers/PhotoHelper";

const countOneLoad = 150;

Expand All @@ -20,11 +33,19 @@ export function useAlbum(
albumIdGetter: MaybeRefOrGetter<number | string>,
photoIdGetter: MaybeRefOrGetter<number | string | undefined>,
) {
const photos = ref<IPhoto[]>([]);
const photosMap = ref<Map<IPhotoKey, IPhoto>>(new Map());
const ownerId = computed(() => toValue(ownerIdGetter));
const albumId = computed(() => toValue(albumIdGetter));
const photoId = computed(() => toValue(photoIdGetter));
const photo = computed(
() =>
photosMap.value?.get(
PhotoHelper.getPhotoKeyOrUndefined(ownerId.value, photoId.value) ??
("" as IPhotoKey),
),
);
const album = ref<IAlbumItem | undefined>();
const photos = ref<IPhoto[]>([]);
const albumRef = ref<InstanceType<typeof RecycleScroller>>();
const { width: widthColumn } = toRefs(AlbumsPreviewSizes);
const initialWidth = computed(() => AlbumsPreviewSizesInitial.value.width);
Expand Down Expand Up @@ -66,10 +87,19 @@ export function useAlbum(
setCurrentPhotoIndex,
setCurrentPhotoId,
onSwitchPhoto,
} = useCurrentPhoto(photos, photoId, isLoadingPhotos, isInit, onMoreLoad);
} = useCurrentPhoto(
photos,
photosMap,
photoId,
ownerId,
isLoadingPhotos,
isInit,
onMoreLoad,
);

const onClearPhotos = () => {
photos.value.length = 0;
photosMap.value.clear();
photosMaxItems.value = 0;
isLoadAllPhotos.value = false;
};
Expand All @@ -91,17 +121,17 @@ export function useAlbum(
albumId.value === "wall"
? []
: (
await useVk()
.getAlbums(ownerId.value)
.catch((ex) => {
if (ex?.errorInfo && ex.errorInfo.error_code !== 15) {
screenError.value = ex;
console.warn("Необработанная ошибка:", ex.errorInfo);
}

return { items: [], count: 0 };
})
).items;
await useVk()
.getAlbums(ownerId.value)
.catch((ex) => {
if (ex?.errorInfo && ex.errorInfo.error_code !== 15) {
screenError.value = ex;
console.warn("Необработанная ошибка:", ex.errorInfo);
}

return { items: [], count: 0 };
})
).items;
albums.push(...getStaticAlbums(ownerId.value));
album.value = albums.find(
(x) => toString(x.id) === toString(albumId.value),
Expand Down Expand Up @@ -144,7 +174,6 @@ export function useAlbum(
watch(
() => useGroups().config.reverseOrder,
async () => {
onClearInit();
onClearError();
onClearPhotos();
await onLoad();
Expand Down Expand Up @@ -179,7 +208,16 @@ export function useAlbum(
isLoadAllPhotos.value = true;
}

photos.value.push(...items);
for (let newPhoto of items) {
newPhoto.__state = {
index: photos.value.length,
};
photosMap.value.set(
PhotoHelper.getPhotoKey(newPhoto.owner_id, newPhoto.id),
newPhoto,
);
photos.value.push(newPhoto);
}
} catch (ex: any) {
alert(ex.message);
screenError.value = ex;
Expand Down Expand Up @@ -208,8 +246,8 @@ export function useAlbum(
[photoId, isLoadingPhotos],
() => {
if (toStr(photoId.value).length && !isLoadingPhotos.value) {
if (currentPhotoIndex.value !== undefined) {
albumRef.value?.scrollToItem(currentPhotoIndex.value);
if (photo.value !== undefined) {
albumRef.value?.scrollToItem(photo.value.__state.index);
} else if (!screenError.value) {
onMoreLoad();
}
Expand Down
65 changes: 16 additions & 49 deletions src/pages/AAlbum/useCurrentPhoto.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { computed, MaybeRefOrGetter, nextTick, Ref, ref, toValue, watch } from "vue";
import { IPhoto } from "vkontakte-api";
import { toStr } from "@/helpers/toStr";
import { computed, nextTick, Ref, ref, watch } from "vue";
import { PhotoHelper } from "@/helpers/PhotoHelper";
import { useRoute, useRouter } from "vue-router";
import { useGroups } from "@/store/groups/groups";
Expand All @@ -9,10 +7,13 @@ import { useElementDeviceSize } from "@/composables/useElementDeviceSize";
import { SwitchPhotoMode } from "@/pages/AAlbum/types";
import { getFirstRefChange } from "@/helpers/getFirstRefChange";
import { useApp } from "@/store/app/app";
import { IPhoto, IPhotoKey } from "@/store/groups/types";

export function useCurrentPhoto(
photosGetter: MaybeRefOrGetter<IPhoto[] | undefined>,
photoIdGetter: MaybeRefOrGetter<number | string | undefined>,
photos: Ref<IPhoto[] | undefined>,
photosMap: Ref<Map<IPhotoKey, IPhoto> | undefined>,
photoId: Ref<number | string | undefined>,
ownerId: Ref<string | number>,
isLoadingPhotos: Ref<boolean>,
isInit: Ref<boolean>,
onMoreLoad: () => void,
Expand All @@ -21,9 +22,6 @@ export function useCurrentPhoto(
const route = useRoute();
const groupsStore = useGroups();
const appStore = useApp();
const photos = computed(() => toValue(photosGetter));
const photoId = computed(() => toValue(photoIdGetter));
// Кэшируем индекс предыдущего найденного фото для оптимизации при перелистывании
const currentPhotoIndex = ref<number | undefined>();
const currentPhoto = computed(() => getPhotoByIndex(currentPhotoIndex.value));

Expand Down Expand Up @@ -77,57 +75,27 @@ export function useCurrentPhoto(
return setCurrentPhotoId(photo?.id);
};

const predictPhotoIndex = computed<number | undefined>(() => {
if (currentPhotoIndex.value === undefined || !photoId.value) {
return undefined;
}

const past = getPhotoByIndex(currentPhotoIndex.value);
if (past?.id == photoId.value) {
return currentPhotoIndex.value;
}

const next = getPhotoByIndex(+currentPhotoIndex.value + 1);
if (next?.id == photoId.value) {
return currentPhotoIndex.value + 1;
}

const prev = getPhotoByIndex(currentPhotoIndex.value - 1);
if (prev?.id == photoId.value) {
return currentPhotoIndex.value - 1;
}

return undefined;
});

watch(
[() => photos.value?.length, photoId, isLoadingPhotos],
() => {
if (!photos.value || !toStr(photoId.value).length) {
if (!photos.value || photoId.value === undefined) {
currentPhotoIndex.value = undefined;
return;
}

if (predictPhotoIndex.value !== undefined) {
currentPhotoIndex.value = predictPhotoIndex.value;
const photo = photosMap.value?.get(
PhotoHelper.getPhotoKey(ownerId.value, photoId.value),
);
if (photo !== undefined) {
currentPhotoIndex.value = photo.__state.index;
return;
}

// если идёт загрузка, то дождёмся её, прежде чем обходить все фото
// если идёт загрузка, то дождёмся её, прежде чем закрывать фото
if (isLoadingPhotos.value) {
return;
}

for (let i = 0; i < photos.value.length; i++) {
const photo = photos.value[i];
if (photo.id != photoId.value) {
continue;
}

currentPhotoIndex.value = i;
return;
}

currentPhotoIndex.value = undefined;
},
{ immediate: true },
Expand Down Expand Up @@ -155,7 +123,7 @@ export function useCurrentPhoto(
getPhotoByIndex(currentIndex)!,
activeElSize,
)
) {
) {
currentIndex = getSwitchPhotoIndexByMode(currentIndex, mode);
if (getPhotoByIndex(currentIndex) !== undefined) {
continue;
Expand All @@ -166,8 +134,7 @@ export function useCurrentPhoto(
await nextTick();

if (isLoadingPhotos.value) {
while (await getFirstRefChange(isLoadingPhotos)) {
}
while (await getFirstRefChange(isLoadingPhotos)) {}
}

await nextTick();
Expand All @@ -182,7 +149,7 @@ export function useCurrentPhoto(
return;
}

let currentIndex = currentPhotoIndex.value;
let currentIndex = currentPhoto.value?.__state.index;
if (currentIndex === undefined) {
return;
}
Expand Down
15 changes: 1 addition & 14 deletions src/pages/AGroups/getGroupState.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,8 @@
import { isNullOrUndefined } from "@/helpers/isNullOrUndefined";
import { IGroup } from "@/store/groups/types";
import { GroupState, IGroup } from "@/store/groups/types";
import { useGroups } from "@/store/groups/groups";
import { isGroupBanned } from "@/helpers/isGroupBanned";

export interface GroupState {
/** @description Отображаемый текст под названием группы */
text: string;
/** @description Группа забанена в ВК */
isBanned?: boolean;
/** @description Требуется отображать кнопку вступления */
isVisibleJoin: boolean;
/** @description Требуется скрыть счётчики */
hideCounters?: boolean;
/** @description Требуется загрузить счётчики */
needLoadingCounters?: boolean;
}

export function getGroupState(group: IGroup): GroupState {
const groupsService = useGroups();
const localGroup = groupsService.getLocalGroupById(group.id);
Expand Down
Loading

0 comments on commit cb5219d

Please sign in to comment.