From c79abadf5a7132e9271c5e55ed30e4aa90b694e8 Mon Sep 17 00:00:00 2001 From: ikotome Date: Sun, 17 Aug 2025 11:50:39 +0900 Subject: [PATCH 1/4] =?UTF-8?q?=E3=83=A9=E3=83=B3=E3=83=80=E3=83=A0?= =?UTF-8?q?=E3=81=8C=E3=81=A7=E3=81=8D=E3=81=8B=E3=81=91=E3=81=A6=E3=81=84?= =?UTF-8?q?=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/debug/TestPage.tsx | 7 +++-- app/view/.index.tsx.swp | Bin 0 -> 16384 bytes app/view/index.tsx | 2 +- ...enRandomFilters.ts => getRandomFilters.ts} | 27 +++++++++--------- 4 files changed, 19 insertions(+), 17 deletions(-) create mode 100644 app/view/.index.tsx.swp rename lib/filters/{genRandomFilters.ts => getRandomFilters.ts} (70%) 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.swp b/app/view/.index.tsx.swp new file mode 100644 index 0000000000000000000000000000000000000000..2e01460f7b85edcf2813a5fbddc4b5f2b7acc3f6 GIT binary patch literal 16384 zcmeI3du$ZP9mls#(*P-Hl&XJ}z6K+eGqLZ^rZ&Vp5*{H%h43(sN`%7R-Q0O$Z}-^U zvoXev@0{=^1d>9aX%H#p5x@ndB%uMCs#T?^twftYnhM%VENA1iDT%76t=d4pGqZcU zcRoW~KvkEk=^%x~s5zxn-s^YA$qT{Lqxc_18>@VZx$e*DnBmJwIpyCeUgB(2mf zJ*}{U>%SCUk3jU=DCZ{bb17&H)AAh1ASfxrTR1p*5M z76>d5SRk;#|BeN$%$?HXQ1_#b%9`{3k+Sz|&MWOa*UQSUI_0MG{6bmzhfeug=lL9` z1Gk@lIOT4;KPxMD#DcfL0)Yhr3j`JjED%^Aus~pezyg5<0t*Bd2rLj-;6Jc{oRFkX zK<)xNZ{zR(?)m@RCnae&px{g3!+Rv@9M}xq2S$*OVUeVJ6Hu~fH7bg zu zmR8sB2kc>|?=vA;lRgT`Ryy6l52J}BW!0o!Z9)=RgE!qo#zv!2e~G0plGQA2BEF|W z6PgHHN?OrUAy>N^(s4UAsPpu?u?EE&CS8@KTAYTKaNXj%W?H58B$G(7HonP{3Gs@N z2)W$7rFZxD>|BqXKW=v)v%62*`4{c(&35-b{`pnA`=H(ZGJFrOtfnLtnrP0*#!8in z1_w-*=zWl?&?9b8*`f<8H|5SaH0wKg;?iqfcJ7;Yev6&kYv-ZdVfW{tDs~EwA;h3o z*3i6BLuXl4sTwkc_RWsX%%XFlPdm5U&YiMz2e?6Q(4n2*ap|=Kg$=t3J$o;1fi3ToQ9L#Tr;`g->DJ-zPA>5am+J})oza};<^!Dhi91nhU>4KhJh zxjobnjh2a&M~e^}5HpsMEeRP>%?q5mvcM7LmBL4q6kW~<-QQC9BD2ruUm)0msu45#HxDC9FeSEHItn#{Wq4P7@V(Q1g*cT(SV z;{+jrm>t~v^GGO2F(;5y>^vgvpa=t~g4upJnWS+m4L0Hl6By;dvHBos-@4 zfmI|$7aB?vF)ah>nuXj)%^ zhN>w2H z!G3uV$?f*{cOD~_pw~h zr88Um&h#Kr_nkc1yK{Zv7}9mm zW}?|e_|EZMq_ie7pUQD7JYyQ_xoJ{T(iz>bh}E8{&YpX&RX#0YBS;$c>@_jcS$|@v5LDw;Svt<5sQ4_xyNF2yYed3-oNfMUJU-PDYL^Ry&KL z1$4E=-kVwWZf>De{1!KKRdwY&|6n!U6`y}rsR04U%pL9rJ{4>n#g(guePrItKVUrk zoo9yP$hh8~MLM99Y-P=V#o;v(^fhf zm6z4xtMt6k6XRWBf@yQRY0czn*1^9v-AH(oJE)7Ov}#yx^sB^6VCj<24}%3 za2PxbmV+hW5ik~v1jE4lIPd=voCiMzJHS@38YIAc!0rdCz~{l;;19SDI0s$@FM@4g z6R^N?!0rvkfiHm1fNQuXxB`9$wu80c>tH$vgAw3e+!I^|Z-F0yZJ-sb0y20Q)Pa%U zUN97#$DP5;;2E$2P%saS00rD1oCB|b=fE?d3s5i%G=k58tGGk>8+Zr24c-9k&S4u^ z4rYKTxF7r-cME;s7vL=D0XsoAFhCl74SW@h1z|7}+yy?sJoSP%!5+{BIzSs}1#BK4 z1Hmh>KwyEu0{>MDuvHK{s02;QS=HiO3AWvuAW5BkhvuB=ENmmN{9@ZUAM04wY$A2e zm7!NMCz-^Kk)06vzLH%kk`^k?hd9Ep{RAOi^=Z1QMDR5F>Y5`}AKvVSgXA`Rl# zq^?=b*oxxJ=yaCRP3%u~4PtW4)K%;oxu|pWN8jkg=_#fg32J!ix;LLmm36^yL=0Kc zVtSjqaF>X?y41P@)y1X?!wT0q3J%tVINd_hwGlh_dcO`f3U;oVD#ur*uq)9LLK~a} z`oFzfT$I@P9)1zXeu}d{&H(H#A^$@=zu)dY;tgJ<7Pi98Ol2(v`;{BtGfR2N&Cg=o znb@`##hD&L*ivaIlAH@{Oo$!0nK13P!5cf;$ru!VsLsjM_RL0(5Jmc+C3KKGQJ-)!fe;D1dx%C7oyM+*Bl_I~U8yl>CZ z>l&HH8C8zc76bwgtmvhrTj92@o<=Grhw2*|YH)Mr{)mR_s~ztbmHBO$lhp`G%SKAk zraJd@Zt@&FPOk68rBUSgYOI*2uCHeu^knww+kFN;T-ds)ziS(_Rf%!jRieJ$2~lSO z!Jn(jY{gOlk~aG@moL>1I!`5Or!g8Gkafgluv;0i7na_j9LO|getIGBF|vLVwm literal 0 HcmV?d00001 diff --git a/app/view/index.tsx b/app/view/index.tsx index 930e2c3..083278d 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 = () => { diff --git a/lib/filters/genRandomFilters.ts b/lib/filters/getRandomFilters.ts similarity index 70% rename from lib/filters/genRandomFilters.ts rename to lib/filters/getRandomFilters.ts index 94d8a98..f20f7b8 100644 --- a/lib/filters/genRandomFilters.ts +++ b/lib/filters/getRandomFilters.ts @@ -1,6 +1,11 @@ import { filterFactory } from "@/lib/filters/FilterFactory"; import type { FilterOptions, OverlayFilterOptions } from "@/types/filters"; +// ギラギラ系のフィルタータイプ +const FILTERS = ["dazzling", "neon", "pachinko", "jewel", "rainbow", "blue", "sepia", "electric", "glitch"]; +import DarkFilter from "@/components/filters/DarkFilter"; + + // フレーム画像をrequireで事前読み込み const FRAME_IMAGES = [ //require("@/assets/flames/gold_frame.png"), @@ -23,24 +28,20 @@ const FRAME_IMAGES = [ * 現在登録されているフィルターから2つをランダムに選ぶユースケース * @returns {[string[], FilterOptions]} ランダムに選択されたフィルター名の配列とオプション */ -export default function getRandomFilters(): [string[], FilterOptions] { - // 登録されている全フィルターのタイプを取得 - const availableFilters = filterFactory.getAvailableFilterTypes(); +export default function getRandomGlitteryFilters(): [string[], FilterOptions] { + const availableGlittery = FILTERS.filter(f => filterFactory.hasFilter(f)); - // フィルターが2つ未満の場合は利用可能な全てを返す - if (availableFilters.length <= 2) { - return [availableFilters, {}]; - } + if (availableGlittery.length === 0) return [[], {}]; - // ランダムに2つ選択 - const shuffled = fisherYatesShuffle(availableFilters); - const selectedFilters = shuffled.slice(0, 2); + // ランダムに2〜3個選択 + const shuffled = fisherYatesShuffle(availableGlittery); + const count = Math.min(3, shuffled.length); // 最大3つ + const selectedFilters = shuffled.slice(0, count); - // オーバーレイフィルターを追加 - selectedFilters.splice(0, 0, "overlay"); + // オーバーレイフィルターを必ず追加 + selectedFilters.unshift("overlay"); const overlayImageUrl = chooseOverlayImageUrl(); - // オーバーレイフィルターのオプションを設定 const options: FilterOptions = overlayImageUrl ? ({ overlayImageUrl, From d7a0cba3a6bd30024df6ecb74dc05b80e8e81ea1 Mon Sep 17 00:00:00 2001 From: ikotome Date: Sun, 17 Aug 2025 12:41:19 +0900 Subject: [PATCH 2/4] =?UTF-8?q?=E3=83=A9=E3=83=B3=E3=83=80=E3=83=A0?= =?UTF-8?q?=E6=A9=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/filters/getRandomFilters.ts | 68 ++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 27 deletions(-) diff --git a/lib/filters/getRandomFilters.ts b/lib/filters/getRandomFilters.ts index f20f7b8..6a96198 100644 --- a/lib/filters/getRandomFilters.ts +++ b/lib/filters/getRandomFilters.ts @@ -1,46 +1,60 @@ import { filterFactory } from "@/lib/filters/FilterFactory"; -import type { FilterOptions, OverlayFilterOptions } from "@/types/filters"; +import type { FilterType, FilterOptions, OverlayFilterOptions } from "@/types/filters"; // ギラギラ系のフィルタータイプ -const FILTERS = ["dazzling", "neon", "pachinko", "jewel", "rainbow", "blue", "sepia", "electric", "glitch"]; -import DarkFilter from "@/components/filters/DarkFilter"; - +const FILTERS: FilterType[] = [ + "dazzling", + "neon", + "pachinko", + "jewel", + "rainbow", + "blue", + // "sepia", + "electric", + "glittery", + "dark", +]; // フレーム画像を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 getRandomGlitteryFilters(): [string[], FilterOptions] { +export default function getRandomGlitteryFilters(): [FilterType[], FilterOptions] { const availableGlittery = FILTERS.filter(f => filterFactory.hasFilter(f)); if (availableGlittery.length === 0) return [[], {}]; - // ランダムに2〜3個選択 + // ランダムに選ぶ(overlay を除く) const shuffled = fisherYatesShuffle(availableGlittery); - const count = Math.min(3, shuffled.length); // 最大3つ - const selectedFilters = shuffled.slice(0, count); + 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", + ]; - // オーバーレイフィルターを必ず追加 - selectedFilters.unshift("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 ? ({ @@ -50,11 +64,11 @@ export default function getRandomGlitteryFilters(): [string[], FilterOptions] { } as OverlayFilterOptions) : {}; - return [selectedFilters, options]; + return [orderedFilters, options]; } function chooseOverlayImageUrl() { - return fisherYatesShuffle(FRAME_IMAGES)[0]; + return FRAME_IMAGES[0]; // 必ず先頭の画像 } function fisherYatesShuffle(array: T[]): T[] { From d8f76a4ae8f3d645d33cd633da7ebc8f9499ad82 Mon Sep 17 00:00:00 2001 From: ikotome Date: Sun, 17 Aug 2025 12:44:34 +0900 Subject: [PATCH 3/4] =?UTF-8?q?=E3=83=90=E3=82=A4=E3=82=AA=E3=83=BC?= =?UTF-8?q?=E3=83=A0=E3=82=84=E3=81=A3=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/view/index.tsx | 36 ++++++++++++++++----------------- lib/filters/getRandomFilters.ts | 24 ++++++++++++++-------- 2 files changed, 34 insertions(+), 26 deletions(-) diff --git a/app/view/index.tsx b/app/view/index.tsx index 297f412..09872c3 100644 --- a/app/view/index.tsx +++ b/app/view/index.tsx @@ -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/getRandomFilters.ts b/lib/filters/getRandomFilters.ts index 6a96198..7eecd98 100644 --- a/lib/filters/getRandomFilters.ts +++ b/lib/filters/getRandomFilters.ts @@ -1,5 +1,9 @@ import { filterFactory } from "@/lib/filters/FilterFactory"; -import type { FilterType, FilterOptions, OverlayFilterOptions } from "@/types/filters"; +import type { + FilterOptions, + FilterType, + OverlayFilterOptions, +} from "@/types/filters"; // ギラギラ系のフィルタータイプ const FILTERS: FilterType[] = [ @@ -16,15 +20,16 @@ const FILTERS: FilterType[] = [ ]; // フレーム画像をrequireで事前読み込み -const FRAME_IMAGES = [ - require("@/assets/flames/gira_photo.png"), -]; +const FRAME_IMAGES = [require("@/assets/flames/gira_photo.png")]; /** * ランダムにフィルターを選ぶが、順序は固定 */ -export default function getRandomGlitteryFilters(): [FilterType[], FilterOptions] { - const availableGlittery = FILTERS.filter(f => filterFactory.hasFilter(f)); +export default function getRandomGlitteryFilters(): [ + FilterType[], + FilterOptions, +] { + const availableGlittery = FILTERS.filter((f) => filterFactory.hasFilter(f)); if (availableGlittery.length === 0) return [[], {}]; @@ -50,9 +55,12 @@ export default function getRandomGlitteryFilters(): [FilterType[], FilterOptions // fixedOrder に沿って並べる(overlay は先頭) const finalFilters = fixedOrder.filter( - f => f === "overlay" || randomSelected.includes(f) + (f) => f === "overlay" || randomSelected.includes(f), ); - const orderedFilters = ["overlay", ...finalFilters.filter(f => f !== "overlay")]; + const orderedFilters = [ + "overlay", + ...finalFilters.filter((f) => f !== "overlay"), + ]; // overlay 用画像 const overlayImageUrl = chooseOverlayImageUrl(); From 7c5e886ca311163fedc393cb4c711debd3c0054e Mon Sep 17 00:00:00 2001 From: ikotome Date: Sun, 17 Aug 2025 12:46:06 +0900 Subject: [PATCH 4/4] =?UTF-8?q?app/view/.index.tsx.swp=E6=B6=88=E3=81=97?= =?UTF-8?q?=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/view/.index.tsx.swp | Bin 16384 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 app/view/.index.tsx.swp diff --git a/app/view/.index.tsx.swp b/app/view/.index.tsx.swp deleted file mode 100644 index 2e01460f7b85edcf2813a5fbddc4b5f2b7acc3f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 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