Przeglądaj źródła

add load more button

Yuki Takei 2 lat temu
rodzic
commit
0c03a713c5

+ 30 - 0
packages/remark-lsx/src/components/Lsx.module.scss

@@ -6,6 +6,36 @@
       animation: lsx-fadeIn 1s ease 0s infinite alternate;
     }
   }
+
+  .lsx-load-more-row {
+    opacity: .5;
+
+    .left-items-label {
+      display: none;
+    }
+    .btn-load-more {
+      border-right-style: hidden;
+      border-bottom-style: hidden;
+      border-left-style: hidden;
+      border-radius: 0;
+    }
+  }
+  .lsx-load-more-row:hover {
+    opacity: 1;
+
+    .left-items-label {
+      display: inline;
+    }
+    .btn-load-more {
+      border-style: solid;
+    }
+  }
+
+  .lsx-load-more-container {
+    max-width: 250px;
+    border-top: 1px black;
+  }
+
 }
 
 @keyframes lsx-fadeIn {

+ 36 - 1
packages/remark-lsx/src/components/Lsx.tsx

@@ -38,7 +38,9 @@ const LsxSubstance = React.memo(({
     return new LsxContext(prefix, options);
   }, [depth, filter, num, prefix, reverse, sort, except]);
 
-  const { data, error, isLoading } = useSWRxLsx(lsxContext.pagePath, lsxContext.options, isImmutable);
+  const {
+    data, error, isLoading, setSize,
+  } = useSWRxLsx(lsxContext.pagePath, lsxContext.options, isImmutable);
 
   const hasError = error != null;
   const errorMessage = error?.message;
@@ -87,11 +89,44 @@ const LsxSubstance = React.memo(({
     return <LsxListView nodeTree={nodeTree} lsxContext={lsxContext} basisViewersCount={basisViewersCount} />;
   }, [data, lsxContext, prefix]);
 
+
+  const LoadMore = useCallback(() => {
+    const lastResult = data?.at(-1);
+
+    if (lastResult == null) {
+      return <></>;
+    }
+
+    const { cursor, total } = lastResult;
+    const leftItemsNum = total - cursor;
+
+    if (leftItemsNum === 0) {
+      return <></>;
+    }
+
+    return (
+      <div className="row justify-content-center lsx-load-more-row">
+        <div className="col-12 col-sm-8 d-flex flex-column align-items-center lsx-load-more-container">
+          <button
+            type="button"
+            className="btn btn btn-block btn-outline-secondary btn-load-more"
+            onClick={() => setSize(size => size + 1)}
+          >
+            Load more<br />
+            <span className="text-muted small left-items-label">({leftItemsNum} pages left)</span>
+          </button>
+        </div>
+      </div>
+    );
+  }, [data, setSize]);
+
+
   return (
     <div className={`lsx ${styles.lsx}`}>
       <Error />
       <Loading />
       {contents}
+      <LoadMore />
     </div>
   );
 });

+ 6 - 1
packages/remark-lsx/src/stores/lsx/lsx.ts

@@ -6,6 +6,9 @@ import type { LsxApiOptions, LsxApiParams, LsxApiResponseData } from '../../inte
 import { parseNumOption } from './parse-num-option';
 
 
+const LOADMORE_PAGES_NUM = 10;
+
+
 export const useSWRxLsx = (
     pagePath: string, options?: Record<string, string|undefined>, isImmutable?: boolean,
 ): SWRInfiniteResponse<LsxApiResponseData, Error> => {
@@ -19,11 +22,13 @@ export const useSWRxLsx = (
     (pageIndex, previousPageData) => {
       if (previousPageData != null && previousPageData.pages.length === 0) return null;
 
+      // the first loading
       if (pageIndex === 0 || previousPageData == null) {
         return ['/_api/lsx', pagePath, options, initialOffsetAndLimit?.offset, initialOffsetAndLimit?.limit, isImmutable];
       }
 
-      return ['/_api/lsx', pagePath, options, previousPageData.cursor, initialOffsetAndLimit?.limit, isImmutable];
+      // loading more
+      return ['/_api/lsx', pagePath, options, previousPageData.cursor, LOADMORE_PAGES_NUM, isImmutable];
     },
     async([endpoint, pagePath, options, offset, limit]) => {
       const apiOptions = Object.assign({}, options, { num: undefined }) as LsxApiOptions;