From 26c3e100504cadcd335cb4a72076a97b1a1b3a2a Mon Sep 17 00:00:00 2001 From: Sakamoto Shiina <68018796+ShiinaSakamoto@users.noreply.github.com> Date: Fri, 27 Dec 2024 10:21:14 +0900 Subject: [PATCH 1/2] [Update] Supporters: Add 'and you' card to the end of them for not making to be alone style whenever flex-style changed. Add and fix some sentences. --- .../setting_box/supporters/Supporters.jsx | 35 ++++++++-- .../supporters/Supporters.module.scss | 64 ++++++++++++++++++ .../supporters_images/supporter_23.png | Bin 0 -> 12104 bytes 3 files changed, 94 insertions(+), 5 deletions(-) create mode 100644 src-ui/assets/supporters/supporters_images/supporter_23.png diff --git a/src-ui/app/config_page/setting_section/setting_box/supporters/Supporters.jsx b/src-ui/app/config_page/setting_section/setting_box/supporters/Supporters.jsx index d8e72d34..8c3d4a76 100644 --- a/src-ui/app/config_page/setting_section/setting_box/supporters/Supporters.jsx +++ b/src-ui/app/config_page/setting_section/setting_box/supporters/Supporters.jsx @@ -9,14 +9,18 @@ import vrct_supporters_title from "@images/supporters/vrct_supporters_title.png" import fanbox_button from "@images/supporters/fanbox_button.png"; 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; const basic_count = 5; const former_count = 2; +const and_you_count = 1; const default_icon_numbers = ["05", "06", "07", "11"]; -const supporters_filenames = Array.from({ length: 22 }, (_, index) => `supporter_${String(index + 1).padStart(2, "0")}`); +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 shuffleArray = (array) => { @@ -36,6 +40,7 @@ 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); @@ -88,7 +93,7 @@ const SupportUsContainer = () => { }; export const SupportersContainer = () => { - const renderImages = (image_list, class_name) => { + const renderImages = (image_list, options={}) => { return image_list.map((file_name) => { const img_src = getSupportersImageByFileName(file_name); const is_default_icon = default_icon_numbers.some((default_num) => file_name.endsWith(default_num)); @@ -100,7 +105,7 @@ export const SupportersContainer = () => { return img_src ? (
@@ -110,6 +115,7 @@ export const SupportersContainer = () => { src={chato_expression_src} /> )} + {options.is_and_you_icon ? : null}
) : null; }); @@ -118,14 +124,33 @@ export const SupportersContainer = () => { return (
-

{`VRCT3.0のアップデートに向けて、むちゃ大変な開発を支えてくれた "Early Supporters" です。\nThey are the 'Early Supporters' who supported us through the incredibly challenging development toward the VRCT3.0 update.`}

+

{`VRCT3.0のアップデートに向けて、めちゃ大変な開発を支えてくれた "Early Supporters" です。\nThey are the 'Early Supporters' who supported us through the incredibly challenging development toward the VRCT3.0 update.`}

- {renderImages(mogu_images, `${styles.mogu_image}`)} + {renderImages(mogu_images, {class_name: styles.mogu_image})} {renderImages(mochi_images)} {renderImages(fuwa_images)} {renderImages(basic_images)} {renderImages(former_images)} + + {renderImages(and_you_images, {is_and_you_icon: true, class_name: styles.and_you_image})} +
+

{`みなさんのおかげで、みしゃ社長は布団で寝ることを許され(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!`}

); }; + +const AndYouIcon = () => { + return ( + <> +
+
+
+
+

+ FANBOX + +

+ + ); +}; \ No newline at end of file diff --git a/src-ui/app/config_page/setting_section/setting_box/supporters/Supporters.module.scss b/src-ui/app/config_page/setting_section/setting_box/supporters/Supporters.module.scss index bd556503..7c0cfc16 100644 --- a/src-ui/app/config_page/setting_section/setting_box/supporters/Supporters.module.scss +++ b/src-ui/app/config_page/setting_section/setting_box/supporters/Supporters.module.scss @@ -128,4 +128,68 @@ width: 2.8rem; transform: translate(-50%, -50%) rotate(10deg); opacity: 0.8; +} + +.and_you_container { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + transition: all 0.3s ease; +} + +.and_you_1, .and_you_2 { + width: 2.2rem; + height: 0.2rem; + border-radius: 50%; + background-color: var(--dark_400_color); +} + +.and_you_2 { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%) rotate(90deg); +} + +.supporter_image_wrapper { + &:hover .and_you_container { + top: 40%; + transform: translate(-50%, -50%) rotate(180deg); + } + &:hover .and_you_fanbox_link_text { + top: 70%; + opacity: 1; + } +} + +.supporter_image_wrapper.and_you_image { + cursor: pointer; + &:active { + opacity: 0.6; + } +} + +.and_you_fanbox_link_text { + font-size: 1.2rem; + color: var(--dark_400_color); + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + transition: all 0.3s ease; + opacity: 0; +} + +.external_link_svg { + color: var(--dark_200_color); + width: 1.2rem; + margin-left: 0.6rem; + padding-bottom: 0.2rem; +} + +.vrct_supporters_desc_end { + font-size: 1.4rem; + margin-top: 2rem; + color: var(--dark_300_color); } \ No newline at end of file diff --git a/src-ui/assets/supporters/supporters_images/supporter_23.png b/src-ui/assets/supporters/supporters_images/supporter_23.png new file mode 100644 index 0000000000000000000000000000000000000000..207be07ebc24f3fcec52b7f96a06003b28075cdd GIT binary patch literal 12104 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 x-SspYJeV5(?H*uk%0XU+jr89D_y~|?#d9fv Date: Fri, 27 Dec 2024 17:26:54 +0900 Subject: [PATCH 2/2] [Update] Supporters: The members cards will be shown in random order every 20 seconds. --- .../setting_section/SettingSection.jsx | 10 +- .../setting_box/supporters/Supporters.jsx | 182 ++++++++++++------ .../supporters/Supporters.module.scss | 10 + src-ui/logics/configs/index.js | 1 + .../configs/useSettingBoxScrollPosition.js | 28 +++ src-ui/store.js | 2 + 6 files changed, 175 insertions(+), 58 deletions(-) create mode 100644 src-ui/logics/configs/useSettingBoxScrollPosition.js diff --git a/src-ui/app/config_page/setting_section/SettingSection.jsx b/src-ui/app/config_page/setting_section/SettingSection.jsx index cfa4c9a2..c39e6221 100644 --- a/src-ui/app/config_page/setting_section/SettingSection.jsx +++ b/src-ui/app/config_page/setting_section/SettingSection.jsx @@ -1,9 +1,17 @@ +import { useRef, useLayoutEffect, useEffect } from "react"; + import styles from "./SettingSection.module.scss"; import { SettingBox } from "./setting_box/SettingBox"; +import { store } from "@store"; export const SettingSection = () => { + const scrollContainerRef = useRef(null); + useLayoutEffect(() => { + store.setting_box_scroll_container = scrollContainerRef; + }, []); + return ( -
+
diff --git a/src-ui/app/config_page/setting_section/setting_box/supporters/Supporters.jsx b/src-ui/app/config_page/setting_section/setting_box/supporters/Supporters.jsx index 8c3d4a76..1d64b9c5 100644 --- a/src-ui/app/config_page/setting_section/setting_box/supporters/Supporters.jsx +++ b/src-ui/app/config_page/setting_section/setting_box/supporters/Supporters.jsx @@ -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 (
@@ -77,10 +50,9 @@ const SupportUsContainer = () => {
@@ -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 ( +
+ +

{`VRCT3.0のアップデートに向けて、めちゃ大変な開発を支えてくれた "Early Supporters" です。\nThey are the 'Early Supporters' who supported us through the incredibly challenging development toward the VRCT3.0 update.`}

+ + + +

{`みなさんのおかげで、みしゃ社長は布団で寝ることを許され(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!`}

+
+ ); +}; + +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 ( +
+ ); +}; + +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,20 +195,15 @@ export const SupportersContainer = () => { }; return ( -
- -

{`VRCT3.0のアップデートに向けて、めちゃ大変な開発を支えてくれた "Early Supporters" です。\nThey are the 'Early Supporters' who supported us through the incredibly challenging development toward the VRCT3.0 update.`}

-
- {renderImages(mogu_images, {class_name: styles.mogu_image})} - {renderImages(mochi_images)} - {renderImages(fuwa_images)} - {renderImages(basic_images)} - {renderImages(former_images)} - - {renderImages(and_you_images, {is_and_you_icon: true, class_name: styles.and_you_image})} - -
-

{`みなさんのおかげで、みしゃ社長は布団で寝ることを許され(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!`}

+
+ {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)} + + {renderImages(imagesState.and_you_images, imagesState.chato_images, { is_and_you_icon: true, class_name: styles.and_you_image })} +
); }; diff --git a/src-ui/app/config_page/setting_section/setting_box/supporters/Supporters.module.scss b/src-ui/app/config_page/setting_section/setting_box/supporters/Supporters.module.scss index 7c0cfc16..4288b653 100644 --- a/src-ui/app/config_page/setting_section/setting_box/supporters/Supporters.module.scss +++ b/src-ui/app/config_page/setting_section/setting_box/supporters/Supporters.module.scss @@ -192,4 +192,14 @@ font-size: 1.4rem; margin-top: 2rem; color: var(--dark_300_color); +} + +.progress_bar { + height: 0.2rem; + width: 0%; + &.progress_bar_active { + transition: width 20000ms linear; + background-color: var(--primary_400_color); + width: 100%; + } } \ No newline at end of file diff --git a/src-ui/logics/configs/index.js b/src-ui/logics/configs/index.js index 646d24c1..b8426255 100644 --- a/src-ui/logics/configs/index.js +++ b/src-ui/logics/configs/index.js @@ -54,4 +54,5 @@ export { useSendTextToOverlay } from "./vr/useSendTextToOverlay"; export { useOscIpAddress } from "./advanced_settings/useOscIpAddress"; export { useOscPort } from "./advanced_settings/useOscPort"; +export { useSettingBoxScrollPosition } from "./useSettingBoxScrollPosition"; export { useSoftwareVersion } from "./useSoftwareVersion"; \ No newline at end of file diff --git a/src-ui/logics/configs/useSettingBoxScrollPosition.js b/src-ui/logics/configs/useSettingBoxScrollPosition.js new file mode 100644 index 00000000..c0a19b98 --- /dev/null +++ b/src-ui/logics/configs/useSettingBoxScrollPosition.js @@ -0,0 +1,28 @@ +import { store, useStore_SettingBoxScrollPosition } from "@store"; + +export const useSettingBoxScrollPosition = () => { + const { currentSettingBoxScrollPosition, updateSettingBoxScrollPosition, pendingSettingBoxScrollPosition } = useStore_SettingBoxScrollPosition(); + + const saveScrollPosition = () => { + if (store.setting_box_scroll_container.current) { + updateSettingBoxScrollPosition(store.setting_box_scroll_container.current.scrollTop); + } + }; + const restoreScrollPosition = () => { + + if (store.setting_box_scroll_container.current) { + updateSettingBoxScrollPosition((pre) => { + store.setting_box_scroll_container.current.scrollTop = pre.data; + return pre.data; + }) + } + + }; + + return { + saveScrollPosition, + restoreScrollPosition, + currentSettingBoxScrollPosition, + updateSettingBoxScrollPosition, + }; +}; \ No newline at end of file diff --git a/src-ui/store.js b/src-ui/store.js index a7950a2a..19d81081 100644 --- a/src-ui/store.js +++ b/src-ui/store.js @@ -16,6 +16,7 @@ import { export const store = { backend_subprocess: null, config_page: null, + setting_box_scroll_container: null, log_box_ref: null, is_applied_init_message_box_height: false, }; @@ -160,6 +161,7 @@ export const { atomInstance: Atom_IsOpenedLanguageSelector, useHook: useStore_Is // Common export const { atomInstance: Atom_SoftwareVersion, useHook: useStore_SoftwareVersion } = createAtomWithHook("-", "SoftwareVersion"); export const { atomInstance: Atom_SelectedConfigTabId, useHook: useStore_SelectedConfigTabId } = createAtomWithHook("device", "SelectedConfigTabId"); +export const { atomInstance: Atom_SettingBoxScrollPosition, useHook: useStore_SettingBoxScrollPosition } = createAtomWithHook(0, "SettingBoxScrollPosition"); // Designs export const { atomInstance: Atom_IsOpenedDropdownMenu, useHook: useStore_IsOpenedDropdownMenu } = createAtomWithHook("", "IsOpenedDropdownMenu");