diff --git a/app/debug/TestPage.tsx b/app/debug/TestPage.tsx index d22a9b5..fa88a00 100644 --- a/app/debug/TestPage.tsx +++ b/app/debug/TestPage.tsx @@ -15,7 +15,7 @@ import { import FilterControls from "@/components/FilterControls"; import FilterView, { type FilterViewRef } from "@/components/FilterView"; import { useFilters } from "@/hooks/useFilters"; -import getRandomFilters from "@/lib/filters/genRandomFilters"; +import getRandomFilters from "@/lib/filters/getRandomFilters"; import type { FilterType } from "@/types/filters"; /** @@ -51,9 +51,10 @@ const TestPage: React.FC = () => { * ランダムフィルター選択のデモハンドラー */ const handleSelectRandomFilters = () => { - const randomFilters = getRandomFilters(); + const [randomFilterTypes, randomOptions] = getRandomFilters(); // ← 配列だけ取り出す + Object.keys(settings.states).forEach((filterType) => { - const shouldEnable = randomFilters.includes(filterType); + const shouldEnable = randomFilterTypes.includes(filterType); // ← 配列に対して includes if (settings.states[filterType as FilterType] !== shouldEnable) { toggleFilter(filterType as FilterType); } diff --git a/app/view/index.tsx b/app/view/index.tsx index 675b9b5..09872c3 100644 --- a/app/view/index.tsx +++ b/app/view/index.tsx @@ -17,7 +17,7 @@ import { } from "react-native"; import FilterView, { type FilterViewRef } from "@/components/FilterView"; import { useFilters } from "@/hooks/useFilters"; -import getRandomFilters from "@/lib/filters/genRandomFilters"; +import getRandomFilters from "@/lib/filters/getRandomFilters"; import type { FilterType } from "@/types/filters"; const ViewPage: React.FC = () => { @@ -400,7 +400,7 @@ const ViewPage: React.FC = () => { {/* アニメーション付き紫ネオン星エフェクト - 写真エリアを避けて配置 */} {starConfigs.map((config, index) => ( + //biome-ignore lint/suspicious/noArrayindex: key={`star-${index}`} style={[ styles.neonStar, @@ -496,23 +496,23 @@ const ViewPage: React.FC = () => { onPress={handlePublishToHub} disabled={hasPublished} > - - - {hasPublished - ? "投稿済み" - : "GILANTIC HUB"} + + + {hasPublished ? "投稿済み" : "GILANTIC HUB"} {!hasPublished && ( - - に公開 - + に公開 )} @@ -564,7 +564,7 @@ const styles = StyleSheet.create({ alignItems: "center", gap: 15, // ボタン間のスペース paddingTop: 10, // 上部にパディング追加 - width: '100%', + width: "100%", }, // 紫ネオン星のスタイル neonStar: { @@ -629,7 +629,7 @@ const styles = StyleSheet.create({ }, publishButtonText: { fontSize: 14, - textAlign: 'center', + textAlign: "center", }, publishButtonSubText: { color: "#fff", diff --git a/lib/filters/genRandomFilters.ts b/lib/filters/genRandomFilters.ts deleted file mode 100644 index 94d8a98..0000000 --- a/lib/filters/genRandomFilters.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { filterFactory } from "@/lib/filters/FilterFactory"; -import type { FilterOptions, OverlayFilterOptions } from "@/types/filters"; - -// フレーム画像をrequireで事前読み込み -const FRAME_IMAGES = [ - //require("@/assets/flames/gold_frame.png"), - //require("@/assets/flames/mirror_frame.png"), - //require("@/assets/flames/mirror_yellow_frame.png"), - //require("@/assets/flames/purple_frame.png"), - //require("@/assets/flames/red_frame.png"), - //require("@/assets/flames/yellow_frame.png"), - //require("@/assets/flames/wabi_orange.png"), - // require("@/assets/flames/gira_green.png"), - // require("@/assets/flames/gira_purple.png"), - // require("@/assets/flames/gira_blue.png"), - // require("@/assets/flames/gira_red.png"), - // require("@/assets/flames/gira_yellow.png"), - // require("@/assets/flames/mirror_orange.png"), - require("@/assets/flames/gira_photo.png"), -]; - -/** - * 現在登録されているフィルターから2つをランダムに選ぶユースケース - * @returns {[string[], FilterOptions]} ランダムに選択されたフィルター名の配列とオプション - */ -export default function getRandomFilters(): [string[], FilterOptions] { - // 登録されている全フィルターのタイプを取得 - const availableFilters = filterFactory.getAvailableFilterTypes(); - - // フィルターが2つ未満の場合は利用可能な全てを返す - if (availableFilters.length <= 2) { - return [availableFilters, {}]; - } - - // ランダムに2つ選択 - const shuffled = fisherYatesShuffle(availableFilters); - const selectedFilters = shuffled.slice(0, 2); - - // オーバーレイフィルターを追加 - selectedFilters.splice(0, 0, "overlay"); - - const overlayImageUrl = chooseOverlayImageUrl(); - // オーバーレイフィルターのオプションを設定 - const options: FilterOptions = overlayImageUrl - ? ({ - overlayImageUrl, - opacity: 1, - blendMode: undefined, - } as OverlayFilterOptions) - : {}; - - return [selectedFilters, options]; -} - -function chooseOverlayImageUrl() { - return fisherYatesShuffle(FRAME_IMAGES)[0]; -} - -function fisherYatesShuffle(array: T[]): T[] { - const shuffled = [...array]; - for (let i = shuffled.length - 1; i > 0; i--) { - const j = Math.floor(Math.random() * (i + 1)); - [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]; - } - return shuffled; -} diff --git a/lib/filters/getRandomFilters.ts b/lib/filters/getRandomFilters.ts new file mode 100644 index 0000000..7eecd98 --- /dev/null +++ b/lib/filters/getRandomFilters.ts @@ -0,0 +1,89 @@ +import { filterFactory } from "@/lib/filters/FilterFactory"; +import type { + FilterOptions, + FilterType, + OverlayFilterOptions, +} from "@/types/filters"; + +// ギラギラ系のフィルタータイプ +const FILTERS: FilterType[] = [ + "dazzling", + "neon", + "pachinko", + "jewel", + "rainbow", + "blue", + // "sepia", + "electric", + "glittery", + "dark", +]; + +// フレーム画像をrequireで事前読み込み +const FRAME_IMAGES = [require("@/assets/flames/gira_photo.png")]; + +/** + * ランダムにフィルターを選ぶが、順序は固定 + */ +export default function getRandomGlitteryFilters(): [ + FilterType[], + FilterOptions, +] { + const availableGlittery = FILTERS.filter((f) => filterFactory.hasFilter(f)); + + if (availableGlittery.length === 0) return [[], {}]; + + // ランダムに選ぶ(overlay を除く) + const shuffled = fisherYatesShuffle(availableGlittery); + const selectedCount = Math.min(2, shuffled.length); // ランダムで2つ + const randomSelected = shuffled.slice(0, selectedCount); + + // フィルター順序を固定 + const fixedOrder: FilterType[] = [ + "neon", + "pachinko", + "electric", + "blue", + "sepia", + "imageMagick", + "glittery", + "jewel", + "dazzling", + "dark", + "overlay", + ]; + + // fixedOrder に沿って並べる(overlay は先頭) + const finalFilters = fixedOrder.filter( + (f) => f === "overlay" || randomSelected.includes(f), + ); + const orderedFilters = [ + "overlay", + ...finalFilters.filter((f) => f !== "overlay"), + ]; + + // overlay 用画像 + const overlayImageUrl = chooseOverlayImageUrl(); + const options: FilterOptions = overlayImageUrl + ? ({ + overlayImageUrl, + opacity: 1, + blendMode: undefined, + } as OverlayFilterOptions) + : {}; + + return [orderedFilters, options]; +} + +function chooseOverlayImageUrl() { + return FRAME_IMAGES[0]; // 必ず先頭の画像 +} + +function fisherYatesShuffle(array: T[]): T[] { + const shuffled = [...array]; + for (let i = shuffled.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]; + } + return shuffled; +}