From c3a13ea340e45d1a9f6be1f1c8dd3567df5cb12d Mon Sep 17 00:00:00 2001
From: lovegaoshi <106490582+lovegaoshi@users.noreply.github.com>
Date: Mon, 11 Nov 2024 13:23:42 -0800
Subject: [PATCH 1/4] feat: vip
---
.vscode/settings.json | 3 ++-
src/App.tsx | 8 ++++++--
src/components/setting/DeveloperSettings.tsx | 8 ++++++++
src/hooks/useSetupPlayer.ts | 8 ++++----
src/hooks/useVIP.ts | 20 ++++++++++++++++++++
src/types/component.d.ts | 3 +++
6 files changed, 43 insertions(+), 7 deletions(-)
create mode 100644 src/hooks/useVIP.ts
diff --git a/.vscode/settings.json b/.vscode/settings.json
index acb5f933..72bceb9a 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -3,5 +3,6 @@
"editor.formatOnSave": true,
"search.exclude": {
"MusicFreePlugins": true
- }
+ },
+ "editor.tabSize": 2
}
diff --git a/src/App.tsx b/src/App.tsx
index aea14652..7d16ca0e 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -16,6 +16,7 @@ import MainBackground from './components/background/MainBackground';
import useTheme from './hooks/useTheme';
// eslint-disable-next-line import/no-unresolved
import { TRACKING } from '@env';
+import useVIP from './hooks/useVIP';
if (TRACKING) {
Sentry.init({
@@ -51,9 +52,12 @@ const APM = ({ PIP, isLandscape }: { PIP: boolean; isLandscape: boolean }) => {
};
export default function App(appProps: NoxComponent.AppProps) {
- const isSplashReady = useSplash(__DEV__ || appProps.intentData ? 1 : 2500);
+ const { vip } = useVIP();
+ const isSplashReady = useSplash(
+ __DEV__ || appProps.intentData || vip ? 1 : 2500,
+ );
const [isSplashAnimReady, setIsSplashReady] = React.useState(false);
- const isPlayerReady = useSetupPlayer(appProps);
+ const isPlayerReady = useSetupPlayer({ ...appProps, vip });
const isLandscape = useIsLandscape();
const PIPMode = useStore(appStore, state => state.pipMode);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
diff --git a/src/components/setting/DeveloperSettings.tsx b/src/components/setting/DeveloperSettings.tsx
index 00baa7b1..36f6c264 100644
--- a/src/components/setting/DeveloperSettings.tsx
+++ b/src/components/setting/DeveloperSettings.tsx
@@ -32,6 +32,7 @@ import {
enableTanaka,
} from '@hooks/useTanakaAmazingCommodities';
import { isAndroid } from '@utils/RNUtils';
+import { purchaseVIP } from '@hooks/useVIP';
enum Icons {
setlog = 'console',
@@ -44,6 +45,7 @@ enum Icons {
fade = 'cosine-wave',
plugins = 'puzzle',
Tanaka = 'emoticon-devil',
+ VIP = 'cash',
}
enum VIEW {
@@ -322,6 +324,12 @@ const Home = ({ navigation }: NoxComponent.StackNavigationProps) => {
}
settingCategory="DeveloperSettings"
/>
+
{
export const appStartupInit = initializePlayer();
-export default ({ intentData }: NoxComponent.AppProps) => {
+export default ({ intentData, vip }: NoxComponent.SetupPlayerProps) => {
const [playerReady, setPlayerReady] = useState(false);
const { updateVersion, checkVersion } = useVersionCheck();
const setIntentData = useNoxSetting(state => state.setIntentData);
const { checkPlayStoreUpdates } = usePlayStore();
useEffect(() => {
- // TODO: if non VIP, call NoxModule?.loadRN() to start loading while displaying
- // splash screen; else, stuff loading in the native splashsceren
- NoxModule?.loadRN();
+ if (!vip) {
+ NoxModule?.loadRN();
+ }
let unmounted = false;
(async () => {
await appStartupInit;
diff --git a/src/hooks/useVIP.ts b/src/hooks/useVIP.ts
new file mode 100644
index 00000000..dbd4fec2
--- /dev/null
+++ b/src/hooks/useVIP.ts
@@ -0,0 +1,20 @@
+import * as SecureStore from 'expo-secure-store';
+import { useState } from 'react';
+
+const VIPKey = 'APMVIP';
+
+export const purchaseVIP = () => {
+ SecureStore.setItemAsync(VIPKey, '1');
+};
+
+export const loseVIP = () => {
+ SecureStore.deleteItemAsync(VIPKey);
+};
+
+const useVIP = () => {
+ const [vip, setVip] = useState(SecureStore.getItem(VIPKey) !== null);
+
+ return { vip };
+};
+
+export default useVIP;
diff --git a/src/types/component.d.ts b/src/types/component.d.ts
index 31a467d5..acd4ae8c 100644
--- a/src/types/component.d.ts
+++ b/src/types/component.d.ts
@@ -14,6 +14,9 @@ declare global {
intentBundle: null | any;
rootTag: number;
}
+ interface SetupPlayerProps extends AppProps {
+ vip?: boolean;
+ }
interface NavigationProps {
navigation: DrawerNavigationProp;
}
From 6ca453190bcd2f7845b03c65e6ef7ee01c30cebf Mon Sep 17 00:00:00 2001
From: lovegaoshi <106490582+lovegaoshi@users.noreply.github.com>
Date: Mon, 11 Nov 2024 14:16:02 -0800
Subject: [PATCH 2/4] feat: vip
---
src/components/billing/bill.ts | 4 ++++
src/utils/Bilibili/BiliUser.ts | 22 +++++++++++++++++++++-
2 files changed, 25 insertions(+), 1 deletion(-)
create mode 100644 src/components/billing/bill.ts
diff --git a/src/components/billing/bill.ts b/src/components/billing/bill.ts
new file mode 100644
index 00000000..21b39dd7
--- /dev/null
+++ b/src/components/billing/bill.ts
@@ -0,0 +1,4 @@
+import { getHasGuard } from '@utils/Bilibili/BiliUser';
+
+//暗精灵和小孩梓尊享APM VIP服务
+const getBiliVIPStatus = () => getHasGuard([529249, 7706705]);
diff --git a/src/utils/Bilibili/BiliUser.ts b/src/utils/Bilibili/BiliUser.ts
index 613cb925..4133cf09 100644
--- a/src/utils/Bilibili/BiliUser.ts
+++ b/src/utils/Bilibili/BiliUser.ts
@@ -5,7 +5,7 @@ import { logger } from '@utils/Logger';
* as "authentication." returns the currently logged in bilibili username.
* @returns dict.
*/
-export default async () => {
+const getUser = async () => {
try {
const val = await fetch('https://api.bilibili.com/x/web-interface/nav');
const res = await val.json();
@@ -17,3 +17,23 @@ export default async () => {
return { uname: '' };
}
};
+
+const getUserGuard = async () => {
+ const uid = (await getUser()).mid;
+ const res = await fetch(
+ `https://api.live.bilibili.com/xlive/web-ucenter/user/MedalWall?target_id=${uid}`,
+ );
+ const data = await res.json();
+
+ return data.data.list;
+};
+
+// simple function that filters is user has guard > 0.
+export const getHasGuard = async (hasGuard: number[] = []) => {
+ const guards = await getUserGuard();
+ return guards.filter(
+ (guard: any) => guard.guard_level > 0 && hasGuard.includes(guard.target_id),
+ );
+};
+
+export default getUser;
From b81d601146ce91be3d76bb95fb7c7767057bbdf9 Mon Sep 17 00:00:00 2001
From: lovegaoshi <106490582+lovegaoshi@users.noreply.github.com>
Date: Mon, 11 Nov 2024 14:46:55 -0800
Subject: [PATCH 3/4] chore: patch
---
...eact-native-draggable-flatlist+4.0.1.patch | 90 +++++++++++++++++++
patches/react-native-reanimated+3.16.1.patch | 17 ----
src/enums/Playlist.ts | 2 +-
src/hooks/usePlayback.migrate.ts | 6 +-
src/hooks/usePlaybackAA.ts | 4 +-
src/hooks/usePlaybackCarplay.ts | 4 +-
6 files changed, 98 insertions(+), 25 deletions(-)
create mode 100644 patches/react-native-draggable-flatlist+4.0.1.patch
delete mode 100644 patches/react-native-reanimated+3.16.1.patch
diff --git a/patches/react-native-draggable-flatlist+4.0.1.patch b/patches/react-native-draggable-flatlist+4.0.1.patch
new file mode 100644
index 00000000..8a3b54b0
--- /dev/null
+++ b/patches/react-native-draggable-flatlist+4.0.1.patch
@@ -0,0 +1,90 @@
+diff --git a/node_modules/react-native-draggable-flatlist/src/components/DraggableFlatList.tsx b/node_modules/react-native-draggable-flatlist/src/components/DraggableFlatList.tsx
+index d7d98c2..2f59c7a 100644
+--- a/node_modules/react-native-draggable-flatlist/src/components/DraggableFlatList.tsx
++++ b/node_modules/react-native-draggable-flatlist/src/components/DraggableFlatList.tsx
+@@ -295,7 +295,7 @@ function DraggableFlatListInner(props: DraggableFlatListProps) {
+ const springTo = placeholderOffset.value - activeCellOffset.value;
+ touchTranslate.value = withSpring(
+ springTo,
+- animationConfigRef.current,
++ animationConfigRef.value,
+ () => {
+ runOnJS(onDragEnd)({
+ from: activeIndexAnim.value,
+diff --git a/node_modules/react-native-draggable-flatlist/src/context/refContext.tsx b/node_modules/react-native-draggable-flatlist/src/context/refContext.tsx
+index ea21575..66c5eed 100644
+--- a/node_modules/react-native-draggable-flatlist/src/context/refContext.tsx
++++ b/node_modules/react-native-draggable-flatlist/src/context/refContext.tsx
+@@ -1,14 +1,14 @@
+ import React, { useContext } from "react";
+ import { useMemo, useRef } from "react";
+ import { FlatList } from "react-native-gesture-handler";
+-import Animated, { WithSpringConfig } from "react-native-reanimated";
++import Animated, { type SharedValue, useSharedValue, WithSpringConfig } from "react-native-reanimated";
+ import { DEFAULT_PROPS } from "../constants";
+ import { useProps } from "./propsContext";
+ import { CellData, DraggableFlatListProps } from "../types";
+
+ type RefContextValue = {
+ propsRef: React.MutableRefObject>;
+- animationConfigRef: React.MutableRefObject;
++ animationConfigRef: SharedValue;
+ cellDataRef: React.MutableRefObject