Improved the wiki section
This commit is contained in:
		
							parent
							
								
									bb42e2a56f
								
							
						
					
					
						commit
						d1d055de29
					
				| @ -1,4 +1,10 @@ | ||||
| import { Dispatch, Fragment, SetStateAction, useState } from "react"; | ||||
| import { | ||||
|   Dispatch, | ||||
|   Fragment, | ||||
|   SetStateAction, | ||||
|   useCallback, | ||||
|   useState, | ||||
| } from "react"; | ||||
| import { Ico, Icon } from "components/Ico"; | ||||
| import { cIf, cJoin } from "helpers/className"; | ||||
| import { useToggle } from "hooks/useToggle"; | ||||
| @ -29,6 +35,11 @@ export const Select = ({ | ||||
|   const [opened, setOpened] = useState(false); | ||||
|   const toggleOpened = useToggle(setOpened); | ||||
| 
 | ||||
|   const tryToggling = useCallback(() => { | ||||
|     const optionCount = options.length + (state === -1 ? 1 : 0); | ||||
|     if (optionCount > 1) toggleOpened(); | ||||
|   }, [options.length, state, toggleOpened]); | ||||
| 
 | ||||
|   return ( | ||||
|     <div | ||||
|       className={cJoin( | ||||
| @ -45,7 +56,7 @@ export const Select = ({ | ||||
|           cIf(opened, "rounded-b-none bg-highlight outline-[transparent]") | ||||
|         )} | ||||
|       > | ||||
|         <p onClick={toggleOpened} className="w-full"> | ||||
|         <p onClick={tryToggling} className="w-full"> | ||||
|           {state === -1 ? "—" : options[state]} | ||||
|         </p> | ||||
|         {state >= 0 && allowEmpty && ( | ||||
| @ -59,7 +70,7 @@ export const Select = ({ | ||||
|           /> | ||||
|         )} | ||||
|         <Ico | ||||
|           onClick={toggleOpened} | ||||
|           onClick={tryToggling} | ||||
|           icon={opened ? Icon.ArrowDropUp : Icon.ArrowDropDown} | ||||
|         /> | ||||
|       </div> | ||||
|  | ||||
| @ -4,6 +4,8 @@ import { ToolTip } from "components/ToolTip"; | ||||
| import { AppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { getStatusDescription } from "helpers/others"; | ||||
| import { useSmartLanguage } from "hooks/useSmartLanguage"; | ||||
| import Link from "next/link"; | ||||
| import { Button } from "components/Inputs/Button"; | ||||
| 
 | ||||
| /* | ||||
|  *                                        ╭─────────────╮ | ||||
| @ -11,7 +13,10 @@ import { useSmartLanguage } from "hooks/useSmartLanguage"; | ||||
|  */ | ||||
| 
 | ||||
| interface Props { | ||||
|   source?: string; | ||||
|   source?: { | ||||
|     name?: string; | ||||
|     url?: string; | ||||
|   }; | ||||
|   translations: { | ||||
|     language: string | undefined; | ||||
|     definition: string | null | undefined; | ||||
| @ -79,9 +84,16 @@ const DefinitionCard = ({ | ||||
|         )} | ||||
|       </div> | ||||
| 
 | ||||
|       <p className="italic">{`${langui.source}: ${source}`}</p> | ||||
| 
 | ||||
|       <p>{selectedTranslation?.definition}</p> | ||||
| 
 | ||||
|       {source?.url && source.name && ( | ||||
|         <Link href={source.url}> | ||||
|           <div className="flex place-items-center gap-2 mt-3"> | ||||
|             <p>{langui.source}: </p> | ||||
|             <Button size="small" text={source.name} /> | ||||
|           </div> | ||||
|         </Link> | ||||
|       )} | ||||
|     </> | ||||
|   ); | ||||
| }; | ||||
|  | ||||
							
								
								
									
										24
									
								
								src/graphql/fragments/source.graphql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/graphql/fragments/source.graphql
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| fragment source on Source { | ||||
|   name | ||||
|   content { | ||||
|     data { | ||||
|       attributes { | ||||
|         slug | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   ranged_content { | ||||
|     data { | ||||
|       attributes { | ||||
|         slug | ||||
|         library_item { | ||||
|           data { | ||||
|             attributes { | ||||
|               slug | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @ -20,6 +20,24 @@ query getWikiPage($slug: String, $language_code: String) { | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         tags { | ||||
|           data { | ||||
|             id | ||||
|             attributes { | ||||
|               slug | ||||
|               titles(filters: { language: { code: { eq: $language_code } } }) { | ||||
|                 language { | ||||
|                   data { | ||||
|                     attributes { | ||||
|                       code | ||||
|                     } | ||||
|                   } | ||||
|                 } | ||||
|                 title | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         translations { | ||||
|           title | ||||
|           aliases { | ||||
| @ -73,7 +91,7 @@ query getWikiPage($slug: String, $language_code: String) { | ||||
|           source { | ||||
|             data { | ||||
|               attributes { | ||||
|                 name | ||||
|                 ...source | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| query getWikiPagesPreviews { | ||||
| query getWikiPagesPreviews($language_code: String) { | ||||
|   wikiPages(pagination: { limit: -1 }) { | ||||
|     data { | ||||
|       id | ||||
| @ -20,6 +20,24 @@ query getWikiPagesPreviews { | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         tags { | ||||
|           data { | ||||
|             id | ||||
|             attributes { | ||||
|               slug | ||||
|               titles(filters: { language: { code: { eq: $language_code } } }) { | ||||
|                 language { | ||||
|                   data { | ||||
|                     attributes { | ||||
|                       code | ||||
|                     } | ||||
|                   } | ||||
|                 } | ||||
|                 title | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         translations { | ||||
|           title | ||||
|           aliases { | ||||
|  | ||||
| @ -23,6 +23,9 @@ import { | ||||
| } from "helpers/others"; | ||||
| import { WikiPageWithTranslations } from "helpers/types"; | ||||
| import { useSmartLanguage } from "hooks/useSmartLanguage"; | ||||
| import { prettySlug } from "helpers/formatters"; | ||||
| import { useLightBox } from "hooks/useLightBox"; | ||||
| import { getAssetURL, ImageQuality } from "helpers/img"; | ||||
| 
 | ||||
| interface Props extends AppStaticProps { | ||||
|   page: WikiPageWithTranslations; | ||||
| @ -45,6 +48,8 @@ const WikiPage = ({ | ||||
|       ), | ||||
|     }); | ||||
| 
 | ||||
|   const [openLightBox, LightBox] = useLightBox(); | ||||
| 
 | ||||
|   const subPanel = useMemo( | ||||
|     () => ( | ||||
|       <SubPanel> | ||||
| @ -63,6 +68,8 @@ const WikiPage = ({ | ||||
|   const contentPanel = useMemo( | ||||
|     () => ( | ||||
|       <ContentPanel width={ContentPanelWidthSizes.Large}> | ||||
|         <LightBox /> | ||||
| 
 | ||||
|         <ReturnButton | ||||
|           href={`/wiki`} | ||||
|           title={langui.wiki} | ||||
| @ -78,7 +85,7 @@ const WikiPage = ({ | ||||
|               <p className="mr-3 text-center text-2xl"> | ||||
|                 {`(${selectedTranslation.aliases | ||||
|                   .map((alias) => alias?.alias) | ||||
|                   .join(", ")})`}
 | ||||
|                   .join("・")})`}
 | ||||
|               </p> | ||||
|             )} | ||||
|           <LanguageSwitcher {...languageSwitcherProps} /> | ||||
| @ -93,19 +100,63 @@ const WikiPage = ({ | ||||
|             text-center" | ||||
|             > | ||||
|               {page.thumbnail?.data?.attributes && ( | ||||
|                 <Img image={page.thumbnail.data.attributes} /> | ||||
|                 <Img | ||||
|                   image={page.thumbnail.data.attributes} | ||||
|                   quality={ImageQuality.Medium} | ||||
|                   className="w-full cursor-pointer" | ||||
|                   onClick={() => { | ||||
|                     if (page.thumbnail?.data?.attributes?.url) { | ||||
|                       openLightBox([ | ||||
|                         getAssetURL( | ||||
|                           page.thumbnail.data.attributes.url, | ||||
|                           ImageQuality.Large | ||||
|                         ), | ||||
|                       ]); | ||||
|                     } | ||||
|                   }} | ||||
|                 /> | ||||
|               )} | ||||
|               <div className="my-4 grid gap-4 p-4"> | ||||
|                 <p className="font-headers text-xl font-bold"> | ||||
|                   {langui.categories} | ||||
|                 </p> | ||||
|                 <div className="flex flex-row flex-wrap place-content-center gap-2"> | ||||
|                   {filterHasAttributes(page.categories?.data, [ | ||||
|                     "attributes", | ||||
|                   ] as const).map((category) => ( | ||||
|                     <Chip key={category.id} text={category.attributes.name} /> | ||||
|                   ))} | ||||
|                 </div> | ||||
|                 {page.categories?.data && page.categories.data.length > 0 && ( | ||||
|                   <> | ||||
|                     <p className="font-headers text-xl font-bold"> | ||||
|                       {langui.categories} | ||||
|                     </p> | ||||
| 
 | ||||
|                     <div className="flex flex-row flex-wrap place-content-center gap-2"> | ||||
|                       {filterHasAttributes(page.categories.data, [ | ||||
|                         "attributes", | ||||
|                       ] as const).map((category) => ( | ||||
|                         <Chip | ||||
|                           key={category.id} | ||||
|                           text={category.attributes.name} | ||||
|                         /> | ||||
|                       ))} | ||||
|                     </div> | ||||
|                   </> | ||||
|                 )} | ||||
| 
 | ||||
|                 {page.tags?.data && page.tags.data.length > 0 && ( | ||||
|                   <> | ||||
|                     <p className="font-headers text-xl font-bold"> | ||||
|                       {/* TODO: Add Tags to langui */} | ||||
|                       {"Tags"} | ||||
|                     </p> | ||||
|                     <div className="flex flex-row flex-wrap place-content-center gap-2"> | ||||
|                       {filterHasAttributes(page.tags?.data, [ | ||||
|                         "attributes", | ||||
|                       ] as const).map((tag) => ( | ||||
|                         <Chip | ||||
|                           key={tag.id} | ||||
|                           text={ | ||||
|                             tag.attributes.titles?.[0]?.title ?? | ||||
|                             prettySlug(tag.attributes.slug) | ||||
|                           } | ||||
|                         /> | ||||
|                       ))} | ||||
|                     </div> | ||||
|                   </> | ||||
|                 )} | ||||
|               </div> | ||||
|             </div> | ||||
| 
 | ||||
| @ -124,7 +175,13 @@ const WikiPage = ({ | ||||
|               <> | ||||
|                 <DefinitionCard | ||||
|                   key={index} | ||||
|                   source={definition.source?.data?.attributes?.name} | ||||
|                   source={{ | ||||
|                     name: definition.source?.data?.attributes?.name, | ||||
|                     url: definition.source?.data?.attributes?.content?.data | ||||
|                       ?.attributes?.slug | ||||
|                       ? `/contents/${definition.source.data.attributes.content.data.attributes.slug}` | ||||
|                       : `/library/${definition.source?.data?.attributes?.ranged_content?.data?.attributes?.library_item?.data?.attributes?.slug}`, | ||||
|                   }} | ||||
|                   translations={definition.translations.map((translation) => ({ | ||||
|                     language: translation?.language?.data?.attributes?.code, | ||||
|                     definition: translation?.definition, | ||||
| @ -149,9 +206,7 @@ const WikiPage = ({ | ||||
|       languageSwitcherProps, | ||||
|       languages, | ||||
|       langui, | ||||
|       page.categories?.data, | ||||
|       page.definitions, | ||||
|       page.thumbnail?.data?.attributes, | ||||
|       page, | ||||
|       selectedTranslation, | ||||
|     ] | ||||
|   ); | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| import { GetStaticProps } from "next"; | ||||
| import { Fragment, useMemo, useState } from "react"; | ||||
| import { useCallback, useMemo, useState } from "react"; | ||||
| import { AppLayout } from "components/AppLayout"; | ||||
| import { NavOption } from "components/PanelComponents/NavOption"; | ||||
| import { PanelHeader } from "components/PanelComponents/PanelHeader"; | ||||
| @ -7,7 +7,7 @@ import { SubPanel } from "components/Panels/SubPanel"; | ||||
| import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { Icon } from "components/Ico"; | ||||
| import { getReadySdk } from "graphql/sdk"; | ||||
| import { GetWikiPagesPreviewsQuery } from "graphql/generated"; | ||||
| import { GetWikiPageQuery, GetWikiPagesPreviewsQuery } from "graphql/generated"; | ||||
| import { | ||||
|   ContentPanel, | ||||
|   ContentPanelWidthSizes, | ||||
| @ -19,8 +19,12 @@ import { Switch } from "components/Inputs/Switch"; | ||||
| import { TextInput } from "components/Inputs/TextInput"; | ||||
| import { WithLabel } from "components/Inputs/WithLabel"; | ||||
| import { useMediaHoverable } from "hooks/useMediaQuery"; | ||||
| import { filterHasAttributes } from "helpers/others"; | ||||
| import { filterDefined, filterHasAttributes, isDefined } from "helpers/others"; | ||||
| import { ContentPlaceholder } from "components/PanelComponents/ContentPlaceholder"; | ||||
| import { SmartList } from "components/SmartList"; | ||||
| import { Select } from "components/Inputs/Select"; | ||||
| import { SelectiveNonNullable } from "helpers/types/SelectiveNonNullable"; | ||||
| import { prettySlug } from "helpers/formatters"; | ||||
| 
 | ||||
| /* | ||||
|  *                                         ╭─────────────╮ | ||||
| @ -30,6 +34,7 @@ import { ContentPlaceholder } from "components/PanelComponents/ContentPlaceholde | ||||
| const DEFAULT_FILTERS_STATE = { | ||||
|   searchName: "", | ||||
|   keepInfoVisible: true, | ||||
|   groupingMethod: -1, | ||||
| }; | ||||
| 
 | ||||
| /* | ||||
| @ -52,13 +57,13 @@ const Wiki = ({ | ||||
|   const [searchName, setSearchName] = useState( | ||||
|     DEFAULT_FILTERS_STATE.searchName | ||||
|   ); | ||||
|   const [keepInfoVisible, setKeepInfoVisible] = useState( | ||||
|     DEFAULT_FILTERS_STATE.keepInfoVisible | ||||
| 
 | ||||
|   const [groupingMethod, setGroupingMethod] = useState<number>( | ||||
|     DEFAULT_FILTERS_STATE.groupingMethod | ||||
|   ); | ||||
| 
 | ||||
|   const filteredPages = useMemo( | ||||
|     () => filterPages(pages, searchName), | ||||
|     [pages, searchName] | ||||
|   const [keepInfoVisible, setKeepInfoVisible] = useState( | ||||
|     DEFAULT_FILTERS_STATE.keepInfoVisible | ||||
|   ); | ||||
| 
 | ||||
|   const subPanel = useMemo( | ||||
| @ -77,6 +82,19 @@ const Wiki = ({ | ||||
|           setState={setSearchName} | ||||
|         /> | ||||
| 
 | ||||
|         <WithLabel | ||||
|           label={langui.group_by} | ||||
|           input={ | ||||
|             <Select | ||||
|               className="w-full" | ||||
|               options={[langui.category ?? ""]} | ||||
|               state={groupingMethod} | ||||
|               setState={setGroupingMethod} | ||||
|               allowEmpty | ||||
|             /> | ||||
|           } | ||||
|         /> | ||||
| 
 | ||||
|         {hoverable && ( | ||||
|           <WithLabel | ||||
|             label={langui.always_show_info} | ||||
| @ -104,59 +122,105 @@ const Wiki = ({ | ||||
|         <NavOption title={langui.chronology} url="/wiki/chronology" border /> | ||||
|       </SubPanel> | ||||
|     ), | ||||
|     [hoverable, keepInfoVisible, langui, searchName] | ||||
|     [groupingMethod, hoverable, keepInfoVisible, langui, searchName] | ||||
|   ); | ||||
| 
 | ||||
|   const groupingFunction = useCallback( | ||||
|     ( | ||||
|       item: SelectiveNonNullable< | ||||
|         NonNullable<GetWikiPageQuery["wikiPages"]>["data"][number], | ||||
|         "attributes" | "id" | ||||
|       > | ||||
|     ): string[] => { | ||||
|       switch (groupingMethod) { | ||||
|         case 0: { | ||||
|           const categories = filterHasAttributes( | ||||
|             item.attributes.categories?.data, | ||||
|             ["attributes"] as const | ||||
|           ); | ||||
|           if (categories.length > 0) { | ||||
|             return categories.map((category) => category.attributes.name); | ||||
|           } | ||||
|           return [langui.no_category ?? "No category"]; | ||||
|         } | ||||
|         default: { | ||||
|           return [""]; | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     [groupingMethod, langui] | ||||
|   ); | ||||
| 
 | ||||
|   const contentPanel = useMemo( | ||||
|     () => ( | ||||
|       <ContentPanel width={ContentPanelWidthSizes.Full}> | ||||
|         <div | ||||
|           className="grid grid-cols-2 items-end gap-8 | ||||
|         desktop:grid-cols-[repeat(auto-fill,_minmax(20rem,1fr))] mobile:gap-4" | ||||
|         > | ||||
|           {filteredPages.length === 0 && ( | ||||
|         <SmartList | ||||
|           items={filterHasAttributes(pages, ["id", "attributes"] as const)} | ||||
|           getItemId={(item) => item.id} | ||||
|           renderItem={({ item }) => ( | ||||
|             <> | ||||
|               {isDefined(item.attributes.translations) && ( | ||||
|                 <TranslatedPreviewCard | ||||
|                   href={`/wiki/${item.attributes.slug}`} | ||||
|                   translations={item.attributes.translations.map( | ||||
|                     (translation) => ({ | ||||
|                       title: translation?.title, | ||||
|                       subtitle: | ||||
|                         translation?.aliases && translation.aliases.length > 0 | ||||
|                           ? translation.aliases | ||||
|                               .map((alias) => alias?.alias) | ||||
|                               .join("・") | ||||
|                           : undefined, | ||||
|                       description: translation?.summary, | ||||
|                       language: translation?.language?.data?.attributes?.code, | ||||
|                     }) | ||||
|                   )} | ||||
|                   thumbnail={item.attributes.thumbnail?.data?.attributes} | ||||
|                   thumbnailAspectRatio={"4/3"} | ||||
|                   thumbnailRounded | ||||
|                   thumbnailForceAspectRatio | ||||
|                   languages={languages} | ||||
|                   slug={item.attributes.slug} | ||||
|                   keepInfoVisible={keepInfoVisible} | ||||
|                   topChips={filterHasAttributes(item.attributes.tags?.data, [ | ||||
|                     "attributes", | ||||
|                   ] as const).map( | ||||
|                     (tag) => | ||||
|                       tag.attributes.titles?.[0]?.title ?? | ||||
|                       prettySlug(tag.attributes.slug) | ||||
|                   )} | ||||
|                   bottomChips={filterHasAttributes( | ||||
|                     item.attributes.categories?.data, | ||||
|                     ["attributes"] as const | ||||
|                   ).map((category) => category.attributes.short)} | ||||
|                 /> | ||||
|               )} | ||||
|             </> | ||||
|           )} | ||||
|           renderWhenEmpty={() => ( | ||||
|             <ContentPlaceholder | ||||
|               message={langui.no_results_message ?? "No results"} | ||||
|               icon={Icon.ChevronLeft} | ||||
|             /> | ||||
|           )} | ||||
|           {filterHasAttributes(filteredPages, [ | ||||
|             "id", | ||||
|             "attributes.translations", | ||||
|           ] as const).map((page) => ( | ||||
|             <Fragment key={page.id}> | ||||
|               <TranslatedPreviewCard | ||||
|                 href={`/wiki/${page.attributes.slug}`} | ||||
|                 translations={page.attributes.translations.map( | ||||
|                   (translation) => ({ | ||||
|                     title: translation?.title, | ||||
|                     subtitle: | ||||
|                       translation?.aliases && translation.aliases.length > 0 | ||||
|                         ? translation.aliases | ||||
|                             .map((alias) => alias?.alias) | ||||
|                             .join(" | ") | ||||
|                         : undefined, | ||||
|                     description: translation?.summary, | ||||
|                     language: translation?.language?.data?.attributes?.code, | ||||
|                   }) | ||||
|                 )} | ||||
|                 thumbnail={page.attributes.thumbnail?.data?.attributes} | ||||
|                 thumbnailAspectRatio={"4/3"} | ||||
|                 thumbnailRounded | ||||
|                 thumbnailForceAspectRatio | ||||
|                 languages={languages} | ||||
|                 slug={page.attributes.slug} | ||||
|                 keepInfoVisible={keepInfoVisible} | ||||
|                 bottomChips={page.attributes.categories?.data.map( | ||||
|                   (category) => category.attributes?.short ?? "" | ||||
|                 )} | ||||
|               /> | ||||
|             </Fragment> | ||||
|           ))} | ||||
|         </div> | ||||
|           langui={langui} | ||||
|           className="grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(20rem,1fr))]" | ||||
|           searchingTerm={searchName} | ||||
|           searchingBy={(item) => | ||||
|             filterDefined(item.attributes.translations) | ||||
|               .map( | ||||
|                 (translation) => | ||||
|                   `${translation.title} ${filterDefined(translation.aliases) | ||||
|                     .map((alias) => alias.alias) | ||||
|                     .join(" ")}` | ||||
|               ) | ||||
|               .join(" ") | ||||
|           } | ||||
|           groupingFunction={groupingFunction} | ||||
|         /> | ||||
|       </ContentPanel> | ||||
|     ), | ||||
|     [filteredPages, keepInfoVisible, languages, langui] | ||||
|     [groupingFunction, keepInfoVisible, languages, langui, pages, searchName] | ||||
|   ); | ||||
| 
 | ||||
|   return ( | ||||
| @ -180,7 +244,9 @@ export default Wiki; | ||||
| 
 | ||||
| export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   const sdk = getReadySdk(); | ||||
|   const pages = await sdk.getWikiPagesPreviews({}); | ||||
|   const pages = await sdk.getWikiPagesPreviews({ | ||||
|     language_code: context.locale ?? "en", | ||||
|   }); | ||||
|   if (!pages.wikiPages?.data) return { notFound: true }; | ||||
|   const props: Props = { | ||||
|     ...(await getAppStaticProps(context)), | ||||
| @ -202,20 +268,3 @@ const sortPages = (pages: Props["pages"]): Props["pages"] => | ||||
|     const slugB = b.attributes?.slug ?? ""; | ||||
|     return slugA.localeCompare(slugB); | ||||
|   }); | ||||
| 
 | ||||
| // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
 | ||||
| 
 | ||||
| const filterPages = (posts: Props["pages"], searchName: string) => | ||||
|   posts.filter((post) => { | ||||
|     if (searchName.length > 1) { | ||||
|       if ( | ||||
|         post.attributes?.translations?.[0]?.title | ||||
|           .toLowerCase() | ||||
|           .includes(searchName.toLowerCase()) === true | ||||
|       ) { | ||||
|         return true; | ||||
|       } | ||||
|       return false; | ||||
|     } | ||||
|     return true; | ||||
|   }); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 DrMint
						DrMint