Skip to content

Commit

Permalink
✨ Feat: 자동 새로고침 추가, 초기 무한스크롤 오류 수정
Browse files Browse the repository at this point in the history
#
  • Loading branch information
qilip committed Nov 7, 2023
1 parent ddaeb4d commit 8f0cd4d
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 19 deletions.
18 changes: 12 additions & 6 deletions components/View/Detail.vue
Original file line number Diff line number Diff line change
Expand Up @@ -447,9 +447,11 @@ const summary = computed(() => {
if (props.document.type === 'IMAGE') {
switch (props.document.status) {
case 'EMBED_PENDING':
return 'AI가 곧 이미지를 분석할거에요.';
return `AI가 곧 이미지를 분석할거에요.
자동으로 진행상황을 확인하고 있어요. 잠시만 기다려주세요...`;
case 'EMBED_PROCESSING':
return 'AI가 이미지를 분석중이에요!';
return `AI가 이미지를 분석중이에요!
자동으로 진행상황을 확인하고 있어요. 잠시만 기다려주세요...`;
case 'EMBED_REJECTED':
return `AI가 이미지 분석에 실패했어요. 다음과 같은 이유일 수 있어요.
1. AI가 분석할 수 없는 이미지 형식이에요.
Expand All @@ -462,19 +464,23 @@ const summary = computed(() => {
}
switch (props.document.status) {
case 'SCRAPE_PENDING':
return '스크랩 대기중이에요.';
return `스크랩 대기중이에요.
자동으로 진행상황을 확인하고 있어요. 잠시만 기다려주세요...`;
case 'SCRAPE_PROCESSING':
return '스크랩이 진행중이에요!';
return `스크랩이 진행중이에요!
자동으로 진행상황을 확인하고 있어요. 잠시만 기다려주세요...`;
case 'SCRAPE_REJECTED':
return `스크랩에 실패했어요. 다음과 같은 이유일 수 있어요.
1. 해당 웹페이지가 존재하지 않거나, 접속할 수 없어요.
2. 해당 웹페이지가 본문을 스크랩할 수 없는 형식이에요.
3. 해당 웹페이지가 스크랩을 거부했어요.
등록 후 2시간동안 자동으로 여러 번 재시도해요. 직접 다시 시도하기를 원한다면 삭제 후 다시 추가해주세요.`;
case 'EMBED_PENDING':
return 'AI가 곧 자료를 요약할거에요.';
return `AI가 곧 자료를 요약할거에요.
자동으로 진행상황을 확인하고 있어요. 잠시만 기다려주세요...`;
case 'EMBED_PROCESSING':
return 'AI가 자료를 요약중이에요!';
return `AI가 자료를 요약중이에요!
자동으로 진행상황을 확인하고 있어요. 잠시만 기다려주세요...`;
case 'EMBED_REJECTED':
return `AI가 자료를 요약하지 못했어요. 다음과 같은 이유일 수 있어요.
1. AI가 요약할 수 없는 형식이에요.
Expand Down
8 changes: 8 additions & 0 deletions pages/collection/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ const isEndOfCollections = computed(() => {
const loadObserverTarget = ref<HTMLElement | null>(null);
const loadObserver = ref<IntersectionObserver | null>(null);
const loadIntersection = ref(false);
onActivated(() => {
initCollection();
Expand All @@ -83,7 +84,10 @@ const setObserver = () => {
loadObserver.value = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting) {
loadIntersection.value = true;
fetchMore();
} else {
loadIntersection.value = false;
}
},
{
Expand Down Expand Up @@ -112,6 +116,8 @@ const initCollection = async () => {
};
});
isLoading.value = false;
if (loadIntersection.value) fetchMore();
};
const fetchMore = async () => {
Expand All @@ -126,6 +132,8 @@ const fetchMore = async () => {
};
});
isLoading.value = false;
if (loadIntersection.value) fetchMore();
};
const isModalOpen = ref(false);
Expand Down
116 changes: 103 additions & 13 deletions pages/main.vue
Original file line number Diff line number Diff line change
Expand Up @@ -97,16 +97,18 @@
<button
ref="updateBtn"
class="h-8 w-8"
:disabled="isLoading"
@click="cleanLoad()"
:disabled="isLoading || autoRefresh"
@click="initLoad()"
>
<svg
xmlns="http://www.w3.org/2000/svg"
height="28"
viewBox="0 -960 960 960"
width="28"
:class="
isLoading
autoRefresh
? 'animate-spin text-blue-400'
: isLoading
? 'animate-spin text-gray-400'
: hasError
? 'text-red-500'
Expand Down Expand Up @@ -253,12 +255,15 @@ const isEndOfDocuments = computed(() => {
});
const loadObserverTarget = ref<HTMLElement | null>(null);
const loadObserver = ref<IntersectionObserver | null>(null);
const loadIntersection = ref(false);
const updateBtn = ref<HTMLElement | null>(null);
const updateObserver = ref<IntersectionObserver | null>(null);
const shouldUpdate = ref(true);
const topIntersection = ref(true);
const autoRefresh = ref(false);
const isLoading = ref(false);
const hasError = ref(false);
const documentStore = useDocumentStore();
Expand Down Expand Up @@ -290,15 +295,9 @@ const shouldFetch = computed(() => {
});
// 모달 생성 주체가 Topbar라서 일단 이렇게 처리
watch(shouldFetch, (newVal) => {
if (newVal === true) {
documentStore.setShouldFetch(false);
cleanLoad();
}
if (newVal === 'cache') {
documentStore.setShouldFetch(false);
initLoad();
}
watch(shouldFetch, async (newVal) => {
if (newVal === true || newVal === 'cache') await initLoad();
documentStore.setShouldFetch(false);
});
onActivated(() => {
Expand All @@ -309,6 +308,7 @@ onActivated(() => {
});
onDeactivated(() => {
clearInterval(todayLoadInterval);
unsetObserver();
});
Expand All @@ -317,7 +317,10 @@ const setObserver = () => {
loadObserver.value = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting) {
loadIntersection.value = true;
loadMore();
} else {
loadIntersection.value = false;
}
},
{
Expand Down Expand Up @@ -376,7 +379,9 @@ const initLoad = async () => {
isLoading.value = false;
hasError.value = false;
if (shouldUpdate.value) cleanLoad();
if (shouldUpdate.value || shouldFetch.value) await cleanLoad();
checkAutoRefresh();
};
const cleanLoad = async () => {
Expand All @@ -397,6 +402,9 @@ const cleanLoad = async () => {
isLoading.value = false;
hasError.value = false;
// 최초 로드 이후 화면에 loadObserver가 있을경우 추가로드
if (loadIntersection.value) loadMore();
};
const loadMore = async () => {
Expand Down Expand Up @@ -425,6 +433,88 @@ const loadMore = async () => {
isLoading.value = false;
hasError.value = false;
// 최초 로드 이후 화면에 loadObserver가 있을경우 추가로드
if (loadIntersection.value) loadMore();
};
const todayLoad = async () => {
isLoading.value = true;
const result = await documentStore.cleanFetch();
if (!result) {
isLoading.value = false;
hasError.value = true;
return;
}
const todayDocs = cardSplitter(result).today;
while (todayDocuments.value.length > todayDocs.length) {
const result = await documentStore.fetchMore();
if (!result) {
isLoading.value = false;
hasError.value = true;
return;
}
const splitedDocs = cardSplitter(result);
todayDocs.push(splitedDocs.today);
if (splitedDocs.today.length === 0) break;
}
todayDocuments.value = todayDocs;
isLoading.value = false;
hasError.value = false;
};
let todayLoadInterval: any = null;
const checkAutoRefresh = () => {
clearInterval(todayLoadInterval); // 이전 인터벌을 정리합니다.
const result = documentStore.getDocuments();
for (const doc of result) {
// 12시간 이내의 문서만 체크합니다.
if (Date.now() - new Date(doc.updatedAt).getTime() > 43200000) break;
// 로드 중인 상태인지 확인합니다.
if (
doc.status === 'SCRAPE_PENDING' ||
doc.status === 'SCRAPE_PROCESSING' ||
(doc.status === 'EMBED_PENDING' && doc.type !== 'MEMO') ||
doc.status === 'EMBED_PROCESSING'
) {
autoRefresh.value = true;
// 2초마다 cleanLoad를 실행합니다.
todayLoadInterval = setInterval(async () => {
await todayLoad();
let loopMore = false;
const newResult = documentStore.getDocuments();
for (const doc of newResult) {
// 12시간 이내의 문서만 체크합니다.
if (Date.now() - new Date(doc.updatedAt).getTime() > 43200000) break;
// 로드 중인 상태인지 확인합니다.
if (
doc.status === 'SCRAPE_PENDING' ||
doc.status === 'SCRAPE_PROCESSING' ||
(doc.status === 'EMBED_PENDING' && doc.type !== 'MEMO') ||
doc.status === 'EMBED_PROCESSING'
) {
loopMore = true;
break;
}
}
if (!loopMore) {
clearInterval(todayLoadInterval);
autoRefresh.value = false;
}
}, 2000);
return; // 로드 중인 문서를 찾았으므로 더 이상 체크할 필요가 없습니다.
}
}
// 로드 중인 문서가 없으면 autoRefresh 상태를 false로 설정합니다.
autoRefresh.value = false;
};
const selectMode = ref(false);
Expand Down
8 changes: 8 additions & 0 deletions pages/search/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ const isEndOfDocuments = computed(() => {
});
const loadObserverTarget = ref<HTMLElement | null>(null);
const loadObserver = ref<IntersectionObserver | null>(null);
const loadIntersection = ref(false);
const searchStore = useSearchStore();
Expand All @@ -197,7 +198,10 @@ const setObserver = () => {
loadObserver.value = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting) {
loadIntersection.value = true;
textSearchMore(query.value);
} else {
loadIntersection.value = false;
}
},
{
Expand Down Expand Up @@ -292,6 +296,8 @@ const textSearch = async (query: string) => {
}
}
isLoading.value = false;
if (loadIntersection.value) textSearchMore(query);
};
const textSearchMore = async (query: string) => {
Expand All @@ -309,6 +315,8 @@ const textSearchMore = async (query: string) => {
}
}
isLoading.value = false;
if (loadIntersection.value) textSearchMore(query);
};
const hybridSearch = async (query: string) => {
Expand Down
8 changes: 8 additions & 0 deletions pages/tag/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ const tags = ref<
const loadObserverTarget = ref<HTMLElement | null>(null);
const loadObserver = ref<IntersectionObserver | null>(null);
const loadIntersection = ref(false);
onActivated(() => {
if (!searchQuery || !searchQuery.value) inital();
Expand All @@ -121,7 +122,10 @@ const setObserver = () => {
loadObserver.value = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting) {
loadIntersection.value = true;
fetchTagsMore();
} else {
loadIntersection.value = false;
}
},
{
Expand Down Expand Up @@ -160,6 +164,8 @@ const inital = async () => {
if (!tags.value.length) tagNotExists.value = true;
else tagNotExists.value = false;
isLoading.value = false;
if (loadIntersection.value) fetchTagsMore();
};
const tagSearch = useDebounceFn(
Expand Down Expand Up @@ -191,6 +197,8 @@ const fetchTagsMore = async () => {
}),
);
isLoading.value = false;
if (loadIntersection.value) fetchTagsMore();
};
const isModalOpen = ref(false);
Expand Down
32 changes: 32 additions & 0 deletions pages/view/[docId].vue
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,41 @@ onDeactivated(() => {
const initialFetch = async () => {
isLoading.value = true;
document.value = await documentStore.fetchDocumentDetail(docId);
if (
(document.value.status === 'SCRAPE_PENDING' ||
document.value.status === 'SCRAPE_PROCESSING' ||
(document.value.status === 'EMBED_PENDING' &&
document.value.type !== 'MEMO') ||
document.value.status === 'EMBED_PROCESSING') &&
new Date().getTime() - new Date(document.value.updatedAt).getTime() <
43200000
) {
autoReload();
}
isLoading.value = false;
};
let autoReloadInterval: any = null;
const autoReload = () => {
autoReloadInterval = setInterval(async () => {
document.value = await documentStore.fetchDocumentDetail(docId);
if (
!(
(document.value.status === 'SCRAPE_PENDING' ||
document.value.status === 'SCRAPE_PROCESSING' ||
(document.value.status === 'EMBED_PENDING' &&
document.value.type !== 'MEMO') ||
document.value.status === 'EMBED_PROCESSING') &&
new Date().getTime() - new Date(document.value.updatedAt).getTime() <
43200000
)
) {
clearInterval(autoReloadInterval);
}
}, 2000);
};
const setObserver = () => {
if (!backBtnObserver.value)
backBtnObserver.value = new IntersectionObserver(
Expand Down

0 comments on commit 8f0cd4d

Please sign in to comment.