@@ -1,7 +1,12 @@
import { useState , useEffect } from "react" ;
import styles from "./Supporters.module.scss" ;
import clsx from "clsx" ;
import { useTranslation } from "react-i18next" ;
import {
useSettingBoxScrollPosition ,
} from "@logics_configs"
const supporter _images = import . meta . glob ( "@images/supporters/supporters_images/*.{png,jpg,jpeg,svg}" , { eager : true } ) ;
const chato _expression _images = import . meta . glob ( "@images/supporters/chato_expressions/*.{png,jpg,jpeg,svg}" , { eager : true } ) ;
import fanbox _img from "@images/supporters/c_fanbox_1620x580.png" ;
@@ -11,7 +16,6 @@ import kofi_preparing from "@images/supporters/kofi_preparing.png";
import ExternalLink from "@images/external_link.svg?react" ;
const mogu _count = 8 ;
const mochi _count = 3 ;
const fuwa _count = 4 ;
@@ -23,6 +27,7 @@ const default_icon_numbers = ["05", "06", "07", "11"];
const supporters _filenames = Array . from ( { length : 23 } , ( _ , index ) => ` supporter_ ${ String ( index + 1 ) . padStart ( 2 , "0" ) } ` ) ;
const chato _expressions _filenames = Array . from ( { length : 7 } , ( _ , index ) => ` chato_expression_ ${ String ( index + 1 ) . padStart ( 2 , "0" ) } ` ) ;
const SHUFFLE _INTERVAL _TIME = 20000 ;
const shuffleArray = ( array ) => {
return array
. map ( ( value ) => ( { value , sort : Math . random ( ) } ) )
@@ -30,38 +35,6 @@ const shuffleArray = (array) => {
. map ( ( { value } ) => value ) ;
} ;
const getCategoryImages = ( start , count ) => {
const category _images = supporters _filenames . slice ( start , start + count ) ;
return shuffleArray ( category _images ) ;
} ;
const mogu _images = getCategoryImages ( 0 , mogu _count ) ;
const mochi _images = getCategoryImages ( mogu _count , mochi _count ) ;
const fuwa _images = getCategoryImages ( mogu _count + mochi _count , fuwa _count ) ;
const basic _images = getCategoryImages ( mogu _count + mochi _count + fuwa _count , basic _count ) ;
const former _images = getCategoryImages ( mogu _count + mochi _count + fuwa _count + basic _count , former _count ) ;
const and _you _images = getCategoryImages ( mogu _count + mochi _count + fuwa _count + basic _count + former _count , and _you _count ) ;
const getRandomImage = ( images ) => {
const random _index = Math . floor ( Math . random ( ) * images . length ) ;
return images [ random _index ] ;
} ;
const getSupportersImageByFileName = ( file _name ) => {
const image _path = Object . keys ( supporter _images ) . find ( ( path ) => path . endsWith ( file _name + ".png" ) ) ;
return image _path ? supporter _images [ image _path ] ? . default : null ;
} ;
const getChatoImageByFileName = ( file _name ) => {
const image _path = Object . keys ( chato _expression _images ) . find ( ( path ) => path . endsWith ( file _name + ".png" ) ) ;
return image _path ? chato _expression _images [ image _path ] ? . default : null ;
} ;
const getRandomDelay = ( min , max ) => {
const random _value = Math . random ( ) * ( max - min ) + min ;
return ` ${ random _value . toFixed ( 1 ) } s ` ;
} ;
export const Supporters = ( ) => {
return (
< div className = { styles . container } >
@@ -77,9 +50,8 @@ const SupportUsContainer = () => {
< img className = { styles . fanbox _img } src = { fanbox _img } / >
< div className = { styles . support _us _button _wrapper } >
< div className = { styles . fanbox _wrapper } >
< a className = { styles . fanbox _button } href = "https://vrct-dev.fanbox.cc/" target = "_blank" rel = "noreferrer" >
{ /* for adjust size to their parent component's width. * /}
< img style = { { height : "100%" , width : "100%" , "objectFit" : "contain" } } src = { fanbox _button } / >
< a className = { styles . fanbox _button } href = "https://vrct-dev.fanbox.cc/" target = "_blank" rel = "noreferrer" >
< img style = { { height : "100%" , width : "100%" , objectFit : "contain" } } src = { fanbox _button } / >
< / a >
< p className = { styles . mainly _japanese } > 日本語 / Mainly Japanese < / p >
< / div >
@@ -92,14 +64,115 @@ const SupportUsContainer = () => {
) ;
} ;
const getRandomImage = ( images ) => {
const random _index = Math . floor ( Math . random ( ) * images . length ) ;
return images [ random _index ] ;
} ;
export const SupportersContainer = ( ) => {
const renderImages = ( image _list , options = { } ) => {
return image _list . map ( ( file _name ) => {
return (
< div className = { styles . supporters _container } >
< img className = { styles . vrct _supporters _title } src = { vrct _supporters _title } / >
< p className = { styles . vrct _supporters _desc } > { ` VRCT3.0のアップデートに向けて、めちゃ大変な開発を支えてくれた "Early Supporters" です。 \ nThey are the 'Early Supporters' who supported us through the incredibly challenging development toward the VRCT3.0 update. ` } < / p >
< ProgressBar / >
< SupportsWrapper / >
< ProgressBar / >
< p className = { styles . vrct _supporters _desc _end } > { ` みなさんのおかげで、みしゃ社長は布団で寝ることを許され(in開発室) しいなは喜び庭駆け回っています! ! ! ふわもちもぐもぐです! ありがとうございます。これからもまだまだ進化するVRCTをどうかよろしくお願いします! \ nThanks to everyone, Misha has been granted the privilege of sleeping in a proper bed (in the development room), and Shiina is so happy, running around the yard! Fuwa-mochi-mogu-mogu! Thank you so much! We hope you'll continue to support the ever-evolving VRCT! ` } < / p >
< / div >
) ;
} ;
const ProgressBar = ( ) => {
const [ is _active , setIsActive ] = useState ( false ) ;
useEffect ( ( ) => {
setIsActive ( true ) ;
const interval = setInterval ( ( ) => {
setIsActive ( false ) ;
setTimeout ( ( ) => setIsActive ( true ) , 50 ) ;
} , SHUFFLE _INTERVAL _TIME ) ;
return ( ) => clearInterval ( interval ) ;
} , [ ] ) ;
return (
< div
className = { clsx ( styles . progress _bar , {
[ styles . progress _bar _active ] : is _active ,
} ) }
/ >
) ;
} ;
const SupportsWrapper = ( ) => {
const { saveScrollPosition , restoreScrollPosition } = useSettingBoxScrollPosition ( ) ;
const [ imagesState , setImagesState ] = useState ( {
mogu _images : [ ] ,
mochi _images : [ ] ,
fuwa _images : [ ] ,
basic _images : [ ] ,
former _images : [ ] ,
and _you _images : [ ] ,
chato _images : [ ] ,
} ) ;
const shuffleImages = ( ) => {
saveScrollPosition ( ) ;
const getCategoryImages = ( start , count ) => {
const category _images = supporters _filenames . slice ( start , start + count ) ;
return shuffleArray ( category _images ) ;
} ;
const randomChatoImages = shuffleArray (
Array . from ( { length : mogu _count + mochi _count + fuwa _count + basic _count + former _count } , ( ) =>
getRandomImage ( chato _expressions _filenames )
)
) ;
setImagesState ( {
mogu _images : getCategoryImages ( 0 , mogu _count ) ,
mochi _images : getCategoryImages ( mogu _count , mochi _count ) ,
fuwa _images : getCategoryImages ( mogu _count + mochi _count , fuwa _count ) ,
basic _images : getCategoryImages ( mogu _count + mochi _count + fuwa _count , basic _count ) ,
former _images : getCategoryImages ( mogu _count + mochi _count + fuwa _count + basic _count , former _count ) ,
and _you _images : getCategoryImages ( mogu _count + mochi _count + fuwa _count + basic _count + former _count , and _you _count ) ,
chato _images : randomChatoImages ,
} ) ;
setTimeout ( ( ) => restoreScrollPosition ( ) , 0 ) ;
} ;
useEffect ( ( ) => {
shuffleImages ( ) ;
const interval = setInterval ( ( ) => {
shuffleImages ( ) ;
} , SHUFFLE _INTERVAL _TIME ) ;
return ( ) => clearInterval ( interval ) ;
} , [ ] ) ;
const getSupportersImageByFileName = ( file _name ) => {
const image _path = Object . keys ( supporter _images ) . find ( ( path ) => path . endsWith ( file _name + ".png" ) ) ;
return image _path ? supporter _images [ image _path ] ? . default : null ;
} ;
const getChatoImageByFileName = ( file _name ) => {
const image _path = Object . keys ( chato _expression _images ) . find ( ( path ) => path . endsWith ( file _name + ".png" ) ) ;
return image _path ? chato _expression _images [ image _path ] ? . default : null ;
} ;
const getRandomDelay = ( min , max ) => {
const random _value = Math . random ( ) * ( max - min ) + min ;
return ` ${ random _value . toFixed ( 1 ) } s ` ;
} ;
const renderImages = ( image _list , chato _list , options = { } ) => {
return image _list . map ( ( file _name , index ) => {
const img _src = getSupportersImageByFileName ( file _name ) ;
const is _default _icon = default _icon _numbers . some ( ( default _num ) => file _name . endsWith ( default _num ) ) ;
const chato _expression _src = is _default _icon
? getChatoImageByFileName ( getRandomImage ( chato _expressions _filenames ) )
: null ;
const is _default _icon = default _icon _numbers . some ( ( element ) => file _name . endsWith ( element ) ) ;
const chato _expression _src = is _default _icon ? getChatoImageByFileName ( chato _list [ index ] ) : null ;
const random _delay = getRandomDelay ( 0.1 , 6 ) ;
return img _src ? (
@@ -122,21 +195,16 @@ export const SupportersContainer = () => {
} ;
return (
< div className = { styles . supporters _container } >
< img className = { styles . vrct _supporters _title } src = { vrct _supporters _title } / >
< p className = { styles . vrct _supporters _desc } > { ` VRCT3.0のアップデートに向けて、めちゃ大変な開発を支えてくれた "Early Supporters" です。 \ nThey are the 'Early Supporters' who supported us through the incredibly challenging development toward the VRCT3.0 update. ` } < / p >
< div className = { styles . supporters _wrapper } >
{ renderImages ( mogu _images , { class _name : styles . mogu _image } ) }
{ renderImages ( mochi _images ) }
{ renderImages ( fuwa _images ) }
{ renderImages ( basic _images ) }
{ renderImages ( former _images ) }
< a href = "https://vrct-dev.fanbox.cc/" target = "_blank" rel = "noreferrer" >
{ renderImages ( and _you _images , { is _and _you _icon : true , class _name : styles . and _you _image } ) }
{ renderImages ( imagesState . mogu_images , imagesState . chato _images , { class _name : styles . mogu _image } ) }
{ renderImages ( imagesState . mochi _images , imagesState . chato _images ) }
{ renderImages ( imagesState . fuwa _images , imagesState . chato _images ) }
{ renderImages ( imagesState . basic _images , imagesState . chato _images ) }
{ renderImages ( imagesState . former _images , imagesState . chato _images ) }
< a href = "https://vrct-dev.fanbox.cc/" target = "_blank" rel = "noreferrer" >
{ renderImages ( imagesState . and_you _images , imagesState . chato _images , { is _and _you _icon : true , class _name : styles . and _you _image } ) }
< / a >
< / div >
< p className = { styles . vrct _supporters _desc _end } > { ` みなさんのおかげで、みしゃ社長は布団で寝ることを許され(in開発室) しいなは喜び庭駆け回っています! ! ! ふわもちもぐもぐです! ありがとうございます。これからもまだまだ進化するVRCTをどうかよろしくお願いします! \ nThanks to everyone, Misha has been granted the privilege of sleeping in a proper bed (in the development room), and Shiina is so happy, running around the yard! Fuwa-mochi-mogu-mogu! Thank you so much! We hope you’ ll continue to support the ever-evolving VRCT! ` } < / p >
< / div >
) ;
} ;