-
-
- 累计访问:次
-
-
+
!open && setOpen(true)}
+ className={classNames(style.info, open && style.open)}
+ >
+
i
bgm素材:
= ({ style }) => {
>
洛天依,言和原创《普通DISCO》
- 、
-
- 贫民百万歌星
-
- 、
-
- 只因你太美
-
玩法来源➡️羊了个羊➡️
@@ -44,6 +29,10 @@ export const Info: FC<{ style?: CSSProperties }> = ({ style }) => {
3 Tiles
+
仅供交流,禁止商用
+
setOpen(false)}>
+ X
+
);
};
diff --git a/src/components/PersonalInfo.module.scss b/src/components/PersonalInfo.module.scss
new file mode 100644
index 0000000..ccd0252
--- /dev/null
+++ b/src/components/PersonalInfo.module.scss
@@ -0,0 +1,137 @@
+@keyframes gradient {
+ 0% {
+ background-position: 0 50%;
+ }
+
+ 50% {
+ background-position: 100% 50%;
+ }
+
+ 100% {
+ background-position: 0 50%;
+ }
+}
+
+.info {
+ position: fixed;
+ right: 8px;
+ top: 8px;
+ padding: 4px;
+ width: 36px;
+ height: 36px;
+ border-radius: 18px;
+ animation: gradient 4s ease infinite;
+ background-image: linear-gradient(
+ -45deg,
+ #ee775288,
+ #e73c7e88,
+ #23a6d588,
+ #23d5ab88
+ );
+ background-size: 400% 400%;
+ background-position: 0 0;
+ box-sizing: border-box;
+ transition: 0.4s;
+ backdrop-filter: blur(8px);
+ z-index: 9;
+ overflow: hidden;
+ color: white;
+
+ * {
+ transition: 0.6s;
+ }
+
+ a {
+ text-decoration: underline;
+ color: white;
+ font-weight: 900;
+ }
+
+ .close {
+ position: absolute;
+ border-radius: 8px;
+ background-color: rgb(0 0 0/20%);
+ width: 36px;
+ height: 36px;
+ right: 0;
+ top: 0;
+ line-height: 36px;
+ text-align: center;
+ transform: scale(0);
+ color: white;
+ cursor: pointer;
+ user-select: none;
+ }
+
+ .github {
+ &Icon {
+ position: absolute;
+ right: 6px;
+ top: 6px;
+ cursor: pointer;
+ }
+
+ &Link {
+ position: absolute;
+ right: -196px;
+ top: 26px;
+ }
+ }
+
+ .bilibili {
+ &Icon {
+ position: absolute;
+ right: -100px;
+ top: 10px;
+ }
+
+ &Link {
+ position: absolute;
+ right: -196px;
+ top: 16px;
+ }
+ }
+
+ &.open {
+ height: 100px;
+ border-radius: 8px;
+
+ @media screen and (max-width: 500px) {
+ width: calc(100% - 16px);
+ }
+ @media screen and (min-width: 501px) {
+ width: 500px;
+ }
+
+ .close {
+ transform: scale(1);
+ }
+
+ .github {
+ &Icon {
+ right: calc(100% - 70px);
+ top: 18px;
+ width: 36px;
+ height: 36px;
+ }
+
+ &Link {
+ right: calc(100% - 200px);
+ top: 26px;
+ }
+ }
+
+ .bilibili {
+ &Icon {
+ height: 36px;
+ right: 26px;
+ top: 50px;
+ }
+
+ &Link {
+ right: 110px;
+ top: 58px;
+ }
+ }
+ }
+}
diff --git a/src/components/PersonalInfo.tsx b/src/components/PersonalInfo.tsx
index 4ae55ff..c2b6f4a 100644
--- a/src/components/PersonalInfo.tsx
+++ b/src/components/PersonalInfo.tsx
@@ -1,56 +1,81 @@
-import React, { FC } from 'react';
+import React, { FC, useState } from 'react';
+import style from './PersonalInfo.module.scss';
+import classNames from 'classnames';
+
+const GithubIcon: FC = () => {
+ return (
+
+ );
+};
+
+const BiliBiliIcon: FC = () => {
+ return (
+
+ );
+};
export const GithubLink: FC = () => {
return (
- 点个✨不迷路 @StreakingMan
-
+ @StreakingMan
);
};
-export const BilibiliLink: FC = () => {
+export const BiliBiliLink: FC = () => {
return (
@streaking_man
-
);
};
export const PersonalInfo: FC = () => {
+ const [open, setOpen] = useState(false);
return (
-
- 、
-
+
!open && setOpen(true)}
+ className={classNames(style.info, open && style.open)}
+ >
+
+
+
+
+
setOpen(false)}>
+ X
+
+
);
};
diff --git a/src/components/ThemeChanger.module.scss b/src/components/ThemeChanger.module.scss
new file mode 100644
index 0000000..c186400
--- /dev/null
+++ b/src/components/ThemeChanger.module.scss
@@ -0,0 +1,48 @@
+.container {
+ position: fixed;
+ right: 8px;
+ bottom: 8px;
+ transition: 0.3s;
+ color: white;
+ backdrop-filter: blur(8px);
+ box-sizing: border-box;
+ cursor: pointer;
+ user-select: none;
+ line-height: 52px;
+ width: 52px;
+ height: 52px;
+ overflow: visible;
+
+ .square {
+ width: 52px;
+ height: 52px;
+ border-radius: 8px;
+ background: rgb(0 0 0/ 40%);
+ position: absolute;
+ right: 0;
+ top: 0;
+ transition: 0.3s;
+ overflow: hidden;
+
+ img {
+ width: 100%;
+ height: 100%;
+ object-fit: contain;
+ }
+ }
+
+ &.open {
+ .diy {
+ width: 80px;
+ font-weight: 900;
+ font-size: 18px;
+ background-image: linear-gradient(
+ -45deg,
+ #ee7752,
+ #e73c7e,
+ #23a6d5,
+ #23d5ab
+ );
+ }
+ }
+}
diff --git a/src/components/ThemeChanger.tsx b/src/components/ThemeChanger.tsx
new file mode 100644
index 0000000..29441f6
--- /dev/null
+++ b/src/components/ThemeChanger.tsx
@@ -0,0 +1,76 @@
+import React, { FC, useState } from 'react';
+import style from './ThemeChanger.module.scss';
+import classNames from 'classnames';
+import { fishermanTheme } from '../themes/fisherman';
+import { jinlunTheme } from '../themes/jinlun';
+import { ikunTheme } from '../themes/ikun';
+import { pddTheme } from '../themes/pdd';
+import { getDefaultTheme } from '../themes/default';
+import { Theme } from '../themes/interface';
+
+const BuiltinThemes = [
+ getDefaultTheme(),
+ fishermanTheme,
+ jinlunTheme,
+ ikunTheme,
+ pddTheme,
+];
+
+export const ThemeChanger: FC<{
+ changeTheme: (theme: Theme
) => void;
+ onDiyClick: () => void;
+}> = ({ changeTheme, onDiyClick }) => {
+ const [open, setOpen] = useState(false);
+ return (
+
+ {BuiltinThemes.map((theme, idx) => (
+
{
+ setOpen(false);
+ changeTheme(theme);
+ }}
+ >
+ {typeof theme.icons[0].content === 'string' ? (
+ theme.icons[0].content.startsWith('http') ? (
+ /*图片外链*/
+

+ ) : (
+ /*字符表情*/
+
{theme.icons[0].content}
+ )
+ ) : (
+ /*ReactNode*/
+ theme.icons[0].content
+ )}
+
+ ))}
+
{
+ setOpen(false);
+ onDiyClick();
+ }}
+ style={{
+ opacity: open ? 1 : 0.3,
+ transform: open ? `translateY(-${110 * 6}%)` : '',
+ }}
+ >
+ DIY!
+
+
setOpen(!open)}
+ className={classNames(style.square)}
+ >
+ {open ? '收起' : '更多'}
+
+
+ );
+};
diff --git a/src/components/Title.module.scss b/src/components/Title.module.scss
new file mode 100644
index 0000000..4519879
--- /dev/null
+++ b/src/components/Title.module.scss
@@ -0,0 +1,63 @@
+@keyframes jump {
+ 0% {
+ transform: translateY(0);
+ }
+
+ 10% {
+ transform: translateY(-50%);
+ }
+
+ 20% {
+ transform: translateY(0);
+ }
+
+ 100% {
+ transform: translateY(0);
+ }
+}
+
+@keyframes scale {
+ 0% {
+ transform: scale(1);
+ }
+
+ 100% {
+ transform: scale(1.05);
+ }
+}
+
+
+.title {
+ margin: 0;
+ line-height: 1.15;
+ font-size: 2rem;
+ padding-top: 1rem;
+ animation: scale 0.27s infinite alternate;
+ z-index: 1;
+
+ * {
+ transition: 0.3s;
+ }
+
+ .item {
+ display: inline-block;
+ animation-name: jump;
+ animation-iteration-count: infinite;
+ animation-duration: 3s;
+ animation-play-state: running;
+ text-shadow: 4px 6px 2px rgb(0 0 0 / 20%);
+ }
+}
+
+.title,
+.description {
+ text-align: center;
+}
+
+.description {
+ margin: 0;
+ line-height: 1.5;
+ font-size: 1rem;
+ font-weight: 400;
+ padding-top: 0.5rem;
+}
diff --git a/src/components/Title.tsx b/src/components/Title.tsx
new file mode 100644
index 0000000..b8190dc
--- /dev/null
+++ b/src/components/Title.tsx
@@ -0,0 +1,24 @@
+import React, { FC } from 'react';
+import style from './Title.module.scss';
+
+export const Title: FC<{ title: string; desc?: string }> = ({
+ title,
+ desc,
+}) => {
+ return (
+ <>
+
+ {[...title].map((str, i) => (
+
+ {str}
+
+ ))}
+
+ {desc && {desc}
}
+ >
+ );
+};
diff --git a/src/main.tsx b/src/main.tsx
index 31f647a..d3f35d3 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -4,6 +4,51 @@ import App from './App';
import './styles/global.scss';
import './styles/utils.scss';
import Bmob from 'hydrogen-js-sdk';
+import {
+ DEFAULT_BGM_STORAGE_KEY,
+ domRelatedOptForTheme,
+ parsePathCustomThemeId,
+ wrapThemeDefaultSounds,
+} from './utils';
+import { getDefaultTheme } from './themes/default';
+import { Theme } from './themes/interface';
+
+// react渲染
+const render = (theme: Theme) => {
+ ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
+
+
+
+ );
+};
+
+// 错误提示
+const errorTip = (tip: string) => {
+ setTimeout(() => {
+ document.getElementById('loading')?.classList.add('error');
+ document.getElementById('loadingText')!.innerText = tip;
+ document.getElementById('backHomeTip')!.style.visibility = 'visible';
+ }, 600);
+};
+
+// 加载成功后数据转换(runtime)以及转场
+const successTrans = (theme: Theme) => {
+ wrapThemeDefaultSounds(theme);
+
+ setTimeout(() => {
+ domRelatedOptForTheme(theme);
+ const root = document.getElementById('root');
+ root!.style.opacity = '0';
+ document.getElementById('loading')?.classList.add('success');
+ setTimeout(() => {
+ render(theme);
+ root!.style.opacity = '1';
+ }, 600);
+ }, 500);
+};
+
+// 从url初始化主题
+const customThemeIdFromPath = parsePathCustomThemeId(location.href);
// Bmob初始化
// @ts-ignore
@@ -12,8 +57,54 @@ Bmob.initialize(
import.meta.env.VITE_BMOB_SECCODE
);
-ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
-
-
-
-);
+const loadTheme = () => {
+ // 请求主题
+ if (customThemeIdFromPath) {
+ const storageTheme = localStorage.getItem(customThemeIdFromPath);
+ if (storageTheme) {
+ try {
+ const customTheme = JSON.parse(storageTheme);
+ successTrans(customTheme);
+ } catch (e) {
+ errorTip('主题配置解析失败');
+ }
+ } else {
+ Bmob.Query('config')
+ .get(customThemeIdFromPath)
+ .then((res) => {
+ const { content } = res as any;
+ localStorage.setItem(customThemeIdFromPath, content);
+ try {
+ const customTheme = JSON.parse(content);
+ successTrans(customTheme);
+ } catch (e) {
+ errorTip('主题配置解析失败');
+ }
+ })
+ .catch(({ error }) => {
+ errorTip(error);
+ });
+ }
+ } else {
+ successTrans(getDefaultTheme());
+ }
+};
+
+// 音效资源请求
+if (!localStorage.getItem(DEFAULT_BGM_STORAGE_KEY)) {
+ const query = Bmob.Query('file');
+ query.equalTo('type', '==', 'default');
+ query
+ .find()
+ .then((results) => {
+ for (const file of results as any) {
+ localStorage.setItem(file.name, file.base64);
+ }
+ loadTheme();
+ })
+ .catch((e) => {
+ errorTip(e);
+ });
+} else {
+ loadTheme();
+}
diff --git a/src/styles/global.scss b/src/styles/global.scss
index c769682..6eadd68 100644
--- a/src/styles/global.scss
+++ b/src/styles/global.scss
@@ -1,11 +1,6 @@
-:root {
- font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
- font-size: 16px;
- line-height: 24px;
- font-weight: 400;
- color-scheme: light dark;
- color: rgb(255 255 255 / 87%);
- background-color: #242424;
+body {
+ padding: 0 32px;
+ -webkit-tap-highlight-color: transparent;
font-synthesis: none;
text-rendering: optimizelegibility;
-webkit-font-smoothing: antialiased;
@@ -13,24 +8,26 @@
text-size-adjust: 100%;
}
-a {
- font-weight: 500;
- color: #646cff;
- text-decoration: inherit;
+#root {
+ text-align: center;
+ width: 100%;
+ max-width: 500px;
+ margin: 0 auto;
+ min-height: 100vh;
+ display: flex;
+ flex-direction: column;
}
-a:hover {
- color: #535bf2;
-}
+button {
+ color: white;
+ border: none;
+ padding: 8px 16px;
+ border-radius: 8px;
+ background-color: #3338;
-body {
- margin: 0;
- padding: 0 32px;
-}
-
-h1 {
- font-size: 3.2em;
- line-height: 1.1;
+ &.primary {
+ background-color: #747bff;
+ }
}
select {
@@ -45,40 +42,4 @@ input {
padding: 8px 12px;
}
-button {
- border-radius: 8px;
- border: 1px solid transparent;
- padding: 0.6em 1.2em;
- font-size: 1em;
- font-weight: 500;
- font-family: inherit;
- background-color: #1a1a1a;
- cursor: pointer;
- transition: border-color 0.25s;
- word-break: keep-all;
- outline: none;
- &.primary {
- background-color: #646cff;
- color: white;
- }
-
- &:hover:not(.primary) {
- border-color: #646cff;
- }
-}
-
-@media (prefers-color-scheme: light) {
- :root {
- color: #213547;
- background-color: #fff;
- }
-
- a:hover {
- color: #747bff;
- }
-
- button {
- background-color: #f9f9f9;
- }
-}
diff --git a/src/styles/utils.scss b/src/styles/utils.scss
index dc777f3..f204e4b 100644
--- a/src/styles/utils.scss
+++ b/src/styles/utils.scss
@@ -4,6 +4,10 @@
flex-wrap: wrap;
}
+.flex-no-wrap {
+ flex-wrap: nowrap;
+}
+
.flex-center {
justify-content: center;
align-items: center;
diff --git a/src/themes/default/index.ts b/src/themes/default/index.ts
index 5a0e86a..e1054f4 100644
--- a/src/themes/default/index.ts
+++ b/src/themes/default/index.ts
@@ -1,4 +1,9 @@
import { Theme } from '../interface';
+import {
+ DEFAULT_BGM_STORAGE_KEY,
+ DEFAULT_CLICK_SOUND_STORAGE_KEY,
+ DEFAULT_TRIPLE_SOUND_STORAGE_KEY,
+} from '../../utils';
const icons = [
`🎨`,
@@ -15,27 +20,31 @@ const icons = [
export type DefaultSoundNames = 'button-click' | 'triple';
-import soundButtonClickUrl from './sounds/sound-button-click.mp3';
-import soundTripleUrl from './sounds/sound-triple.mp3';
-export const defaultSounds: Theme['sounds'] = [
- {
- name: 'button-click',
- src: soundButtonClickUrl,
- },
- {
- name: 'triple',
- src: soundTripleUrl,
- },
-];
-
-export const defaultTheme: Theme = {
- title: '有解的羊了个羊(DEMO)',
- name: '默认',
- icons: icons.map((icon) => ({
- name: icon,
- content: icon,
- clickSound: 'button-click',
- tripleSound: 'triple',
- })),
- sounds: defaultSounds,
+export const getDefaultTheme: () => Theme = () => {
+ return {
+ title: '有解的羊了个羊',
+ desc: '真的可以通关~',
+ dark: true,
+ backgroundColor: '#8dac85',
+ icons: icons.map((icon) => ({
+ name: icon,
+ content: icon,
+ clickSound: 'button-click',
+ tripleSound: 'triple',
+ })),
+ sounds: [
+ {
+ name: 'button-click',
+ src:
+ localStorage.getItem(DEFAULT_CLICK_SOUND_STORAGE_KEY) || '',
+ },
+ {
+ name: 'triple',
+ src:
+ localStorage.getItem(DEFAULT_TRIPLE_SOUND_STORAGE_KEY) ||
+ '',
+ },
+ ],
+ bgm: localStorage.getItem(DEFAULT_BGM_STORAGE_KEY) || '',
+ };
};
diff --git a/src/themes/default/sounds/sound-button-click.mp3 b/src/themes/default/sounds/sound-button-click.mp3
deleted file mode 100644
index 39b8ee6..0000000
Binary files a/src/themes/default/sounds/sound-button-click.mp3 and /dev/null differ
diff --git a/src/themes/default/sounds/sound-triple.mp3 b/src/themes/default/sounds/sound-triple.mp3
deleted file mode 100644
index f6f06be..0000000
Binary files a/src/themes/default/sounds/sound-triple.mp3 and /dev/null differ
diff --git a/src/themes/fisherman/index.tsx b/src/themes/fisherman/index.tsx
index 2185bd7..953f6b7 100644
--- a/src/themes/fisherman/index.tsx
+++ b/src/themes/fisherman/index.tsx
@@ -1,7 +1,7 @@
// 钓鱼佬主题
import React from 'react';
import { Theme } from '../interface';
-import { DefaultSoundNames, defaultSounds } from '../default';
+import { DefaultSoundNames } from '../default';
const imagesUrls = import.meta.glob('./images/*.png', {
import: 'default',
@@ -17,12 +17,11 @@ const fishes = Object.entries(imagesUrls).map(([key, value]) => ({
export const fishermanTheme: Theme = {
title: '🐟鱼了个鱼🐟',
- name: '钓鱼佬',
icons: fishes.map(({ name, content }) => ({
name,
content,
clickSound: 'button-click',
tripleSound: 'triple',
})),
- sounds: defaultSounds,
+ sounds: [],
};
diff --git a/src/themes/ikun/index.tsx b/src/themes/ikun/index.tsx
index 5747922..e9401ee 100644
--- a/src/themes/ikun/index.tsx
+++ b/src/themes/ikun/index.tsx
@@ -53,7 +53,6 @@ const icons = Object.entries(imagesUrls).map(([key, value]) => ({
export const ikunTheme: Theme = {
title: '🐔鸡了个鸡🐔',
- name: 'iKun',
bgm,
icons: icons.map(({ name, content }) => ({
name,
diff --git a/src/themes/interface.ts b/src/themes/interface.ts
index 08b4951..8f3078d 100644
--- a/src/themes/interface.ts
+++ b/src/themes/interface.ts
@@ -14,14 +14,14 @@ export interface Sound {
type Operation = 'shift' | 'undo' | 'wash';
-// TODO title name 冗余
export interface Theme {
title: string;
- desc?: ReactNode;
- name: string;
+ desc?: string;
bgm?: string;
background?: string;
+ backgroundColor?: string;
backgroundBlur?: boolean;
+ dark?: boolean;
pure?: boolean;
icons: Icon[];
sounds: Sound[];
diff --git a/src/themes/jinlun/index.tsx b/src/themes/jinlun/index.tsx
index 78ab71c..cbeb7b1 100644
--- a/src/themes/jinlun/index.tsx
+++ b/src/themes/jinlun/index.tsx
@@ -25,7 +25,6 @@ const icons = Object.entries(imagesUrls).map(([key, value]) => ({
export const jinlunTheme: Theme = {
title: '🐎马了个马🐎',
- name: '金轮',
icons: icons.map(({ name, content }) => ({
name,
content,
diff --git a/src/themes/ow/images/ow.png b/src/themes/ow/images/ow.png
deleted file mode 100644
index 83ed96c..0000000
Binary files a/src/themes/ow/images/ow.png and /dev/null differ
diff --git a/src/themes/ow/images/上勾拳.png b/src/themes/ow/images/上勾拳.png
deleted file mode 100644
index 4c34d14..0000000
Binary files a/src/themes/ow/images/上勾拳.png and /dev/null differ
diff --git a/src/themes/ow/images/你倒是跑啊.png b/src/themes/ow/images/你倒是跑啊.png
deleted file mode 100644
index aaba22a..0000000
Binary files a/src/themes/ow/images/你倒是跑啊.png and /dev/null differ
diff --git a/src/themes/ow/images/吃个娜娜.png b/src/themes/ow/images/吃个娜娜.png
deleted file mode 100644
index 37f2b00..0000000
Binary files a/src/themes/ow/images/吃个娜娜.png and /dev/null differ
diff --git a/src/themes/ow/images/末日铁拳来了.png b/src/themes/ow/images/末日铁拳来了.png
deleted file mode 100644
index 0d3f502..0000000
Binary files a/src/themes/ow/images/末日铁拳来了.png and /dev/null differ
diff --git a/src/themes/ow/images/杀人哥嘎嘎.png b/src/themes/ow/images/杀人哥嘎嘎.png
deleted file mode 100644
index dc76be5..0000000
Binary files a/src/themes/ow/images/杀人哥嘎嘎.png and /dev/null differ
diff --git a/src/themes/ow/images/李甲抡.png b/src/themes/ow/images/李甲抡.png
deleted file mode 100644
index 69f8667..0000000
Binary files a/src/themes/ow/images/李甲抡.png and /dev/null differ
diff --git a/src/themes/ow/images/毁天灭地.png b/src/themes/ow/images/毁天灭地.png
deleted file mode 100644
index 0265e27..0000000
Binary files a/src/themes/ow/images/毁天灭地.png and /dev/null differ
diff --git a/src/themes/ow/images/离开嗷ruai.png b/src/themes/ow/images/离开嗷ruai.png
deleted file mode 100644
index 172cb7a..0000000
Binary files a/src/themes/ow/images/离开嗷ruai.png and /dev/null differ
diff --git a/src/themes/ow/images/脑瘫.png b/src/themes/ow/images/脑瘫.png
deleted file mode 100644
index fd2ba67..0000000
Binary files a/src/themes/ow/images/脑瘫.png and /dev/null differ
diff --git a/src/themes/ow/index.tsx b/src/themes/ow/index.tsx
deleted file mode 100644
index 4ba3348..0000000
--- a/src/themes/ow/index.tsx
+++ /dev/null
@@ -1,50 +0,0 @@
-import { Theme } from '../interface';
-import React from 'react';
-import { defaultSounds } from '../default';
-
-const soundUrls = import.meta.glob('./sounds/*.mp3', {
- import: 'default',
- eager: true,
-});
-
-const sounds = Object.entries(soundUrls).map(([key, value]) => ({
- name: key.slice(9, -4),
- src: value,
-})) as Theme['sounds'];
-
-const imagesUrls = import.meta.glob('./images/*.png', {
- import: 'default',
- eager: true,
-});
-
-const icons = Object.entries(imagesUrls).map(([key, value]) => ({
- name: key.slice(9, -4),
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- content:
,
-}));
-
-export const owTheme: Theme = {
- title: '守望先锋',
- desc: (
-
- 感谢
-
- 白板特工华南虎
-
- 提供素材
-
- ),
- name: 'OW',
- icons: icons.map(({ name, content }) => ({
- name,
- content,
- clickSound: 'button-click',
- tripleSound: name === 'ow' ? 'triple' : name,
- })),
- sounds: [...defaultSounds, ...sounds],
-};
diff --git a/src/themes/ow/sounds/上勾拳.mp3 b/src/themes/ow/sounds/上勾拳.mp3
deleted file mode 100644
index 14ea09f..0000000
Binary files a/src/themes/ow/sounds/上勾拳.mp3 and /dev/null differ
diff --git a/src/themes/ow/sounds/你倒是跑啊.mp3 b/src/themes/ow/sounds/你倒是跑啊.mp3
deleted file mode 100644
index 3bfdf0c..0000000
Binary files a/src/themes/ow/sounds/你倒是跑啊.mp3 and /dev/null differ
diff --git a/src/themes/ow/sounds/吃个娜娜.mp3 b/src/themes/ow/sounds/吃个娜娜.mp3
deleted file mode 100644
index a9d6a92..0000000
Binary files a/src/themes/ow/sounds/吃个娜娜.mp3 and /dev/null differ
diff --git a/src/themes/ow/sounds/末日铁拳来了.mp3 b/src/themes/ow/sounds/末日铁拳来了.mp3
deleted file mode 100644
index 1bc1c57..0000000
Binary files a/src/themes/ow/sounds/末日铁拳来了.mp3 and /dev/null differ
diff --git a/src/themes/ow/sounds/杀人哥嘎嘎.mp3 b/src/themes/ow/sounds/杀人哥嘎嘎.mp3
deleted file mode 100644
index 235b7de..0000000
Binary files a/src/themes/ow/sounds/杀人哥嘎嘎.mp3 and /dev/null differ
diff --git a/src/themes/ow/sounds/李甲抡.mp3 b/src/themes/ow/sounds/李甲抡.mp3
deleted file mode 100644
index 9bb5bfc..0000000
Binary files a/src/themes/ow/sounds/李甲抡.mp3 and /dev/null differ
diff --git a/src/themes/ow/sounds/毁天灭地.mp3 b/src/themes/ow/sounds/毁天灭地.mp3
deleted file mode 100644
index ae3ae87..0000000
Binary files a/src/themes/ow/sounds/毁天灭地.mp3 and /dev/null differ
diff --git a/src/themes/ow/sounds/离开嗷ruai.mp3 b/src/themes/ow/sounds/离开嗷ruai.mp3
deleted file mode 100644
index 201d43f..0000000
Binary files a/src/themes/ow/sounds/离开嗷ruai.mp3 and /dev/null differ
diff --git a/src/themes/ow/sounds/脑瘫.mp3 b/src/themes/ow/sounds/脑瘫.mp3
deleted file mode 100644
index 299ec00..0000000
Binary files a/src/themes/ow/sounds/脑瘫.mp3 and /dev/null differ
diff --git a/src/themes/pdd/index.tsx b/src/themes/pdd/index.tsx
index 231a5b0..e639d06 100644
--- a/src/themes/pdd/index.tsx
+++ b/src/themes/pdd/index.tsx
@@ -1,7 +1,6 @@
// 骚猪主题
import React from 'react';
import { Theme } from '../interface';
-import { defaultSounds } from '../default';
import bgm from './sounds/bgm.mp3';
const soundUrls = import.meta.glob('./sounds/*.mp3', {
@@ -28,20 +27,7 @@ const images = Object.entries(imagesUrls).map(([key, value]) => ({
export const pddTheme: Theme = {
title: '🐷猪了个猪🐷',
- desc: (
-
- 感谢
-
- 猪酱的日常
-
- 提供素材
-
- ),
- name: '骚猪',
+ desc: '感谢 @猪酱的日常 提供素材',
bgm: bgm,
icons: images.map(({ name, content }) => ({
name,
@@ -49,5 +35,5 @@ export const pddTheme: Theme = {
clickSound: 'button-click',
tripleSound: name,
})),
- sounds: [defaultSounds[0], ...sounds],
+ sounds,
};
diff --git a/src/utils.ts b/src/utils.ts
index 441d5da..439b4fa 100644
--- a/src/utils.ts
+++ b/src/utils.ts
@@ -1,4 +1,11 @@
import { Theme } from './themes/interface';
+import { getDefaultTheme } from './themes/default';
+
+export const LAST_LEVEL_STORAGE_KEY = 'lastLevel';
+export const LAST_SCORE_STORAGE_KEY = 'lastScore';
+export const DEFAULT_BGM_STORAGE_KEY = 'defaultBgm';
+export const DEFAULT_TRIPLE_SOUND_STORAGE_KEY = 'defaultTripleSound';
+export const DEFAULT_CLICK_SOUND_STORAGE_KEY = 'defaultClickSound';
export const randomString: (len: number) => string = (len) => {
const pool = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
@@ -18,14 +25,7 @@ export const waitTimeout: (timeout: number) => Promise = (timeout) => {
});
};
-// 从url获取内置主题name
-export const parsePathThemeName: (url: string) => string = (url) => {
- const urlObj = new URL(url);
- const params = urlObj.searchParams;
- return decodeURIComponent(params.get('theme') || '默认');
-};
-
-// 从url解析自定义主题JSON
+// 从url获取自定义主题Id
export const parsePathCustomThemeId: (url: string) => string = (url) => {
const urlObj = new URL(url);
const params = urlObj.searchParams;
@@ -63,3 +63,47 @@ export const captureElement = (id: string, filename: string) => {
1
);
};
+
+export const wrapThemeDefaultSounds: (theme: Theme) => void = (theme) => {
+ const defaultTheme = getDefaultTheme();
+ // 默认音频资源补充
+ if (!theme.bgm) {
+ theme.bgm = defaultTheme.bgm;
+ }
+ let hasUseDefaultTriple, hasUseDefaultClick;
+ for (const icon of theme.icons) {
+ if (!icon.clickSound) icon.clickSound = 'button-click';
+ if (!icon.tripleSound) icon.tripleSound = 'triple';
+ if (icon.clickSound === 'button-click') hasUseDefaultClick = true;
+ if (icon.tripleSound === 'triple') hasUseDefaultTriple = true;
+ }
+ if (
+ hasUseDefaultClick &&
+ !theme.sounds.find((s) => s.name === 'button-click')
+ ) {
+ const defaultClick = defaultTheme.sounds.find(
+ (s) => s.name === 'button-click'
+ );
+ defaultClick && theme.sounds.push(defaultClick);
+ }
+ if (hasUseDefaultTriple && !theme.sounds.find((s) => s.name === 'triple')) {
+ const defaultTripleSound = defaultTheme.sounds.find(
+ (s) => s.name === 'triple'
+ );
+ defaultTripleSound && theme.sounds.push(defaultTripleSound);
+ }
+
+ // 兼容旧数据
+ for (const sound of theme.sounds) {
+ if (['triple', 'button-click'].includes(sound.name))
+ // @ts-ignore
+ sound.src = defaultTheme.sounds.find(
+ (s) => s.name === sound.name
+ ).src;
+ }
+};
+
+export const domRelatedOptForTheme = (theme: Theme) => {
+ document.body.style.backgroundColor = theme.backgroundColor || 'white';
+ document.body.style.color = theme.dark ? 'white' : 'rgb(0 0 0 / 60%)';
+};