迁移仓库

This commit is contained in:
2026-02-24 09:55:08 +08:00
parent 2d5c056b82
commit df6210aaf7
30 changed files with 1121 additions and 81 deletions

View File

@@ -28,6 +28,13 @@
20CC02D32D150A1C0001B529 /* DSAvatarCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 20CC02D12D150A1C0001B529 /* DSAvatarCollectionViewCell.xib */; };
20DA04E42CD32AEF003530CA /* DSWebDragView.m in Sources */ = {isa = PBXBuildFile; fileRef = 20DA04E02CD32AEF003530CA /* DSWebDragView.m */; };
20DA04E52CD32AEF003530CA /* WMDragView.m in Sources */ = {isa = PBXBuildFile; fileRef = 20DA04E12CD32AEF003530CA /* WMDragView.m */; };
891A21472EAF3C4D008F03B3 /* GDWebPageHookService.m in Sources */ = {isa = PBXBuildFile; fileRef = 891A21422EAF3C4D008F03B3 /* GDWebPageHookService.m */; };
891A21482EAF3C4D008F03B3 /* GDWebURLSessionDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 891A21462EAF3C4D008F03B3 /* GDWebURLSessionDelegate.m */; };
891A21492EAF3C4D008F03B3 /* WKWebView+GDWebURLSchemeHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 891A213D2EAF3C4D008F03B3 /* WKWebView+GDWebURLSchemeHandler.m */; };
891A214A2EAF3C4D008F03B3 /* GDWebAssetStorageService.m in Sources */ = {isa = PBXBuildFile; fileRef = 891A21402EAF3C4D008F03B3 /* GDWebAssetStorageService.m */; };
891A214B2EAF3C4D008F03B3 /* GDWebURLSchemeHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 891A213B2EAF3C4D008F03B3 /* GDWebURLSchemeHandler.m */; };
891A214C2EAF3C4D008F03B3 /* GDWebURLSessionService.m in Sources */ = {isa = PBXBuildFile; fileRef = 891A21442EAF3C4D008F03B3 /* GDWebURLSessionService.m */; };
891A23692EC3178B008F03B3 /* GameWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 891A23682EC3178B008F03B3 /* GameWebViewController.m */; };
896EC2172D4081AE00732103 /* CoreTelephony.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 896EC2162D4081AE00732103 /* CoreTelephony.framework */; };
89A55AD72D4210CF0000FE0F /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 89A55AD62D4210CF0000FE0F /* GoogleService-Info.plist */; };
9D06CD612B70B72500A5CDF7 /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D06CD602B70B72500A5CDF7 /* libc++.tbd */; };
@@ -123,6 +130,21 @@
20DA04E32CD32AEF003530CA /* WMDragView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WMDragView.h; sourceTree = "<group>"; };
2770952325ADBC033AEA844E /* Pods_SQNoti.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SQNoti.framework; sourceTree = BUILT_PRODUCTS_DIR; };
30D1D837206E6AC5F27F4CB4 /* Pods-ShenQi.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShenQi.release.xcconfig"; path = "Target Support Files/Pods-ShenQi/Pods-ShenQi.release.xcconfig"; sourceTree = "<group>"; };
891A213A2EAF3C4D008F03B3 /* GDWebURLSchemeHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GDWebURLSchemeHandler.h; sourceTree = "<group>"; };
891A213B2EAF3C4D008F03B3 /* GDWebURLSchemeHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GDWebURLSchemeHandler.m; sourceTree = "<group>"; };
891A213C2EAF3C4D008F03B3 /* WKWebView+GDWebURLSchemeHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "WKWebView+GDWebURLSchemeHandler.h"; sourceTree = "<group>"; };
891A213D2EAF3C4D008F03B3 /* WKWebView+GDWebURLSchemeHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "WKWebView+GDWebURLSchemeHandler.m"; sourceTree = "<group>"; };
891A213E2EAF3C4D008F03B3 /* GDWebCustomURLSchemeProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GDWebCustomURLSchemeProtocol.h; sourceTree = "<group>"; };
891A213F2EAF3C4D008F03B3 /* GDWebAssetStorageService.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GDWebAssetStorageService.h; sourceTree = "<group>"; };
891A21402EAF3C4D008F03B3 /* GDWebAssetStorageService.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GDWebAssetStorageService.m; sourceTree = "<group>"; };
891A21412EAF3C4D008F03B3 /* GDWebPageHookService.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GDWebPageHookService.h; sourceTree = "<group>"; };
891A21422EAF3C4D008F03B3 /* GDWebPageHookService.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GDWebPageHookService.m; sourceTree = "<group>"; };
891A21432EAF3C4D008F03B3 /* GDWebURLSessionService.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GDWebURLSessionService.h; sourceTree = "<group>"; };
891A21442EAF3C4D008F03B3 /* GDWebURLSessionService.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GDWebURLSessionService.m; sourceTree = "<group>"; };
891A21452EAF3C4D008F03B3 /* GDWebURLSessionDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GDWebURLSessionDelegate.h; sourceTree = "<group>"; };
891A21462EAF3C4D008F03B3 /* GDWebURLSessionDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GDWebURLSessionDelegate.m; sourceTree = "<group>"; };
891A23672EC3178B008F03B3 /* GameWebViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameWebViewController.h; sourceTree = "<group>"; };
891A23682EC3178B008F03B3 /* GameWebViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameWebViewController.m; sourceTree = "<group>"; };
896EC2162D4081AE00732103 /* CoreTelephony.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreTelephony.framework; path = System/Library/Frameworks/CoreTelephony.framework; sourceTree = SDKROOT; };
89A55AD62D4210CF0000FE0F /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
9D06CD602B70B72500A5CDF7 /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; };
@@ -249,6 +271,8 @@
20CC02C92D141B650001B529 /* LaunchViewController.xib */,
207022AD2CD8C1C10061657B /* MainOldViewController.h */,
207022AE2CD8C1C10061657B /* MainOldViewController.m */,
891A23672EC3178B008F03B3 /* GameWebViewController.h */,
891A23682EC3178B008F03B3 /* GameWebViewController.m */,
9D834B862D320969005B7327 /* NotiCenterViewController.h */,
9D834B872D320969005B7327 /* NotiCenterViewController.m */,
9D834B882D320969005B7327 /* NotiCenterViewController.xib */,
@@ -271,6 +295,19 @@
9D834BA22D3214C2005B7327 /* PushRecordData.m */,
9D834BA42D3214C3005B7327 /* PushRecordList.h */,
9D834BA12D3214C2005B7327 /* PushRecordList.m */,
891A213A2EAF3C4D008F03B3 /* GDWebURLSchemeHandler.h */,
891A213B2EAF3C4D008F03B3 /* GDWebURLSchemeHandler.m */,
891A213C2EAF3C4D008F03B3 /* WKWebView+GDWebURLSchemeHandler.h */,
891A213D2EAF3C4D008F03B3 /* WKWebView+GDWebURLSchemeHandler.m */,
891A213E2EAF3C4D008F03B3 /* GDWebCustomURLSchemeProtocol.h */,
891A213F2EAF3C4D008F03B3 /* GDWebAssetStorageService.h */,
891A21402EAF3C4D008F03B3 /* GDWebAssetStorageService.m */,
891A21412EAF3C4D008F03B3 /* GDWebPageHookService.h */,
891A21422EAF3C4D008F03B3 /* GDWebPageHookService.m */,
891A21432EAF3C4D008F03B3 /* GDWebURLSessionService.h */,
891A21442EAF3C4D008F03B3 /* GDWebURLSessionService.m */,
891A21452EAF3C4D008F03B3 /* GDWebURLSessionDelegate.h */,
891A21462EAF3C4D008F03B3 /* GDWebURLSessionDelegate.m */,
89A55AD62D4210CF0000FE0F /* GoogleService-Info.plist */,
20B317F32CD4BA6700B29987 /* YYModel */,
20DA04DF2CD32AEF003530CA /* WMDragView */,
@@ -355,6 +392,7 @@
TargetAttributes = {
20B61C7729DC008500CE7946 = {
CreatedOnToolsVersion = 14.2;
LastSwiftMigration = 1640;
};
};
};
@@ -455,6 +493,12 @@
buildActionMask = 2147483647;
files = (
9D834BAC2D321722005B7327 /* UIButton+DSButtonBlock.m in Sources */,
891A21472EAF3C4D008F03B3 /* GDWebPageHookService.m in Sources */,
891A21482EAF3C4D008F03B3 /* GDWebURLSessionDelegate.m in Sources */,
891A21492EAF3C4D008F03B3 /* WKWebView+GDWebURLSchemeHandler.m in Sources */,
891A214A2EAF3C4D008F03B3 /* GDWebAssetStorageService.m in Sources */,
891A214B2EAF3C4D008F03B3 /* GDWebURLSchemeHandler.m in Sources */,
891A214C2EAF3C4D008F03B3 /* GDWebURLSessionService.m in Sources */,
20CC02D22D150A1C0001B529 /* DSAvatarCollectionViewCell.m in Sources */,
20DA04E42CD32AEF003530CA /* DSWebDragView.m in Sources */,
9D834B8F2D320BC2005B7327 /* NotiCenterTableViewCell.m in Sources */,
@@ -468,6 +512,7 @@
20B61C7D29DC008500CE7946 /* AppDelegate.m in Sources */,
207022AF2CD8C1C10061657B /* MainOldViewController.m in Sources */,
20CC02C52D14183A0001B529 /* ConfigDataModel.m in Sources */,
891A23692EC3178B008F03B3 /* GameWebViewController.m in Sources */,
20CC02C62D14183A0001B529 /* ConfigData.m in Sources */,
20B61C8E29DC008800CE7946 /* main.m in Sources */,
20B317F92CD4BA6800B29987 /* YYClassInfo.m in Sources */,
@@ -642,18 +687,19 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = ShenQi/ShenQiDebug.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 78T95AT28H;
DEVELOPMENT_TEAM = 89Y643YWG7;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/ShenQi",
);
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = ShenQi/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = RAPID97;
INFOPLIST_KEY_CFBundleDisplayName = Nova9;
INFOPLIST_KEY_NSAppleMusicUsageDescription = "需要访问相册权限用于照片上传,应用不会上传和存储您的照片";
INFOPLIST_KEY_NSCameraUsageDescription = "需要相机权限用于拍照上传,应用不会上传和存储您的照片";
INFOPLIST_KEY_NSContactsUsageDescription = "用于匹配您的好友";
@@ -665,7 +711,7 @@
INFOPLIST_KEY_UIMainStoryboardFile = Main;
INFOPLIST_KEY_UIRequiresFullScreen = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = UIInterfaceOrientationPortrait;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
@@ -675,14 +721,16 @@
"$(inherited)",
"$(PROJECT_DIR)/ShenQi",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = noti.RAPID97;
MARKETING_VERSION = 1.5;
PRODUCT_BUNDLE_IDENTIFIER = noti.NO1VA9SG4;
PRODUCT_NAME = TESTAPP;
PROVISIONING_PROFILE_SPECIFIER = "";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
@@ -693,18 +741,19 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = ShenQi/ShenQiRelease.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 78T95AT28H;
DEVELOPMENT_TEAM = 89Y643YWG7;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/ShenQi",
);
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = ShenQi/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = RAPID97;
INFOPLIST_KEY_CFBundleDisplayName = Nova9;
INFOPLIST_KEY_NSAppleMusicUsageDescription = "需要访问相册权限用于照片上传,应用不会上传和存储您的照片";
INFOPLIST_KEY_NSCameraUsageDescription = "需要相机权限用于拍照上传,应用不会上传和存储您的照片";
INFOPLIST_KEY_NSContactsUsageDescription = "用于匹配您的好友";
@@ -716,7 +765,7 @@
INFOPLIST_KEY_UIMainStoryboardFile = Main;
INFOPLIST_KEY_UIRequiresFullScreen = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = UIInterfaceOrientationPortrait;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
@@ -726,14 +775,15 @@
"$(inherited)",
"$(PROJECT_DIR)/ShenQi",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = noti.RAPID97;
MARKETING_VERSION = 1.5;
PRODUCT_BUNDLE_IDENTIFIER = noti.NO1VA9SG4;
PRODUCT_NAME = TESTAPP;
PROVISIONING_PROFILE_SPECIFIER = "";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;

View File

@@ -3,4 +3,18 @@
uuid = "8C3A038C-0CB6-445A-A27C-084577E8C5CA"
type = "0"
version = "2.0">
<Breakpoints>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.ExceptionBreakpoint">
<BreakpointContent
uuid = "4B613790-7E9F-4906-844F-5F338E1E79E2"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
breakpointStackSelectionBehavior = "1"
scope = "1"
stopOnStyle = "0">
</BreakpointContent>
</BreakpointProxy>
</Breakpoints>
</Bucket>

View File

@@ -1,7 +1,7 @@
{
"images" : [
{
"filename" : "微信图片_20250819133612_1137.jpg",
"filename" : "app_logo.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"

Binary file not shown.

After

Width:  |  Height:  |  Size: 769 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 KiB

View File

@@ -1,7 +1,7 @@
{
"images" : [
{
"filename" : "微信图片_20250819133612_1137.jpg",
"filename" : "app_logo.png",
"idiom" : "universal",
"scale" : "1x"
},

Binary file not shown.

After

Width:  |  Height:  |  Size: 769 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 KiB

View File

@@ -26,7 +26,7 @@
</imageView>
</subviews>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
<color key="backgroundColor" red="0.074509806930000005" green="0.15686275059999999" blue="0.55294120309999995" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="wWz-RR-gyr" firstAttribute="centerY" secondItem="6Tk-OE-BBY" secondAttribute="centerY" constant="-40" id="CqV-4e-F3I"/>
<constraint firstItem="wWz-RR-gyr" firstAttribute="centerX" secondItem="6Tk-OE-BBY" secondAttribute="centerX" id="FHK-Fd-BPL"/>

View File

@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="CLX-jd-tRb">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23727" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="CLX-jd-tRb">
<device id="retina6_12" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23721"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
@@ -55,15 +55,15 @@
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="jWy-uW-8Li" customClass="DSWebDragView">
<rect key="frame" x="0.0" y="408.66666666666669" width="60" height="60"/>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="jWy-uW-8Li" customClass="DSWebDragView">
<rect key="frame" x="0.0" y="421" width="60" height="60"/>
<constraints>
<constraint firstAttribute="height" constant="60" id="XG1-uZ-BDG"/>
<constraint firstAttribute="width" secondItem="jWy-uW-8Li" secondAttribute="height" multiplier="1:1" id="yzH-EX-jDa"/>
</constraints>
</view>
<collectionView hidden="YES" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="rsS-Qz-Fg1" customClass="DSWebMenuCollectionView">
<rect key="frame" x="0.0" y="271.66666666666669" width="60" height="334.00000000000006"/>
<collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="rsS-Qz-Fg1" customClass="DSWebMenuCollectionView">
<rect key="frame" x="0.0" y="284" width="60" height="334"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstAttribute="width" constant="60" id="gU5-UR-beg"/>
@@ -105,7 +105,7 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="appLogo" translatesAutoresizingMaskIntoConstraints="NO" id="keb-Jy-qyA">
<rect key="frame" x="96.666666666666686" y="298.66666666666669" width="200" height="200"/>
<rect key="frame" x="96.666666666666686" y="311" width="200" height="200"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="width" constant="200" id="B9b-Wy-kPu"/>
@@ -114,7 +114,7 @@
</imageView>
</subviews>
<viewLayoutGuide key="safeArea" id="cX4-SA-T7x"/>
<color key="backgroundColor" red="0.078431375319999996" green="0.15294116739999999" blue="0.55294120309999995" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="keb-Jy-qyA" firstAttribute="centerX" secondItem="cX4-SA-T7x" secondAttribute="centerX" id="PJ3-c1-DbO"/>
<constraint firstItem="keb-Jy-qyA" firstAttribute="centerY" secondItem="cX4-SA-T7x" secondAttribute="centerY" constant="-40" id="S3L-dn-yjZ"/>

View File

@@ -0,0 +1,23 @@
//
// GDWebAssetStorageService.h
// DESThreeTest
//
// Created by Qwerdf on 2025/10/24.
// Copyright © 2025 zhang alan. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "GDWebCustomURLSchemeProtocol.h"
NS_ASSUME_NONNULL_BEGIN
@interface GDWebAssetStorageService : NSObject <GDWebCustomURLSchemeProtocol>
/// 存储需要处理的请求任务
@property (nonatomic, strong) id<WKURLSchemeTask> schemeTask;
/// 处理完成的回调
@property (nonatomic, copy) void(^completion)(void);
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,83 @@
//
// GDWebAssetStorageService.m
// DESThreeTest
//
// Created by Qwerdf on 2025/10/24.
// Copyright © 2025 zhang alan. All rights reserved.
//
#import "GDWebAssetStorageService.h"
@implementation GDWebAssetStorageService
#pragma mark -
- (instancetype)initWithSchemeTask:(id<WKURLSchemeTask>)task {
if (self = [super init]) {
_schemeTask = task;
}
return self;
}
#pragma mark - GDWebCustomURLSchemeProtocol
+ (BOOL)canService:(id<WKURLSchemeTask>)task {
// "asset://"
NSString *scheme = task.request.URL.scheme.lowercaseString;
return [scheme isEqualToString:@"asset"];
}
- (void)startLoading:(void (^)(void))completion {
self.completion = completion;
NSURLRequest *request = self.schemeTask.request;
NSURL *url = request.URL;
// 1. asset://images/logo.png -> images/logo.png
NSString *path = [url.path stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"/"]];
NSString *localPath = [[NSBundle mainBundle] pathForResource:path ofType:nil];
if (!localPath) {
// Documents
NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:path];
localPath = docPath;
}
// 2.
if ([[NSFileManager defaultManager] fileExistsAtPath:localPath]) {
NSData *data = [NSData dataWithContentsOfFile:localPath];
NSString *mimeType = [self mimeTypeForPath:localPath];
NSURLResponse *response = [[NSURLResponse alloc] initWithURL:url
MIMEType:mimeType
expectedContentLength:data.length
textEncodingName:@"UTF-8"];
//
[self.schemeTask didReceiveResponse:response];
[self.schemeTask didReceiveData:data];
[self.schemeTask didFinish];
} else {
// 404
NSError *error = [NSError errorWithDomain:NSURLErrorDomain
code:NSURLErrorFileDoesNotExist
userInfo:@{NSLocalizedDescriptionKey: @"本地资源不存在"}];
[self.schemeTask didFailWithError:error];
}
//
if (completion) completion();
}
- (void)stopLoading {
//
self.schemeTask = nil;
if (self.completion) self.completion();
}
#pragma mark - MIME
- (NSString *)mimeTypeForPath:(NSString *)path {
NSString *extension = [path pathExtension].lowercaseString;
if ([extension isEqualToString:@"html"]) return @"text/html";
if ([extension isEqualToString:@"js"]) return @"application/javascript";
if ([extension isEqualToString:@"css"]) return @"text/css";
if ([extension isEqualToString:@"png"]) return @"image/png";
if ([extension isEqualToString:@"jpg"] || [extension isEqualToString:@"jpeg"]) return @"image/jpeg";
return @"application/octet-stream";
}
@end

View File

@@ -0,0 +1,33 @@
//
// GDWebCustomURLSchemeProtocol.h
// DESThreeTest
//
// Created by Qwerdf on 2025/10/24.
// Copyright © 2025 zhang alan. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <WebKit/WebKit.h>
NS_ASSUME_NONNULL_BEGIN
@protocol GDWebCustomURLSchemeProtocol <NSObject>
/// 初始化方法,传入需要处理的请求任务
/// @param task WKURLSchemeTask 对象(包含请求信息和回调方法)
- (instancetype)initWithSchemeTask:(id<WKURLSchemeTask>)task;
/// 开始处理请求
/// @param completion 处理完成后的回调(用于移除任务缓存)
- (void)startLoading:(void(^)(void))completion;
/// 停止处理请求(如网页取消加载时调用)
- (void)stopLoading;
/// 类方法:判断当前服务是否能处理该请求
/// @param task 待处理的请求任务
+ (BOOL)canService:(id<WKURLSchemeTask>)task;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,23 @@
//
// GDWebPageHookService.h
// DESThreeTest
//
// Created by Qwerdf on 2025/10/24.
// Copyright © 2025 zhang alan. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "GDWebCustomURLSchemeProtocol.h"
NS_ASSUME_NONNULL_BEGIN
@interface GDWebPageHookService : NSObject <GDWebCustomURLSchemeProtocol>
@property (nonatomic, strong) id<WKURLSchemeTask> schemeTask;
@property (nonatomic, copy) void(^completion)(void);
/// 用于网络请求的会话
@property (nonatomic, strong) NSURLSessionDataTask *dataTask;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,80 @@
//
// GDWebPageHookService.m
// DESThreeTest
//
// Created by Qwerdf on 2025/10/24.
// Copyright © 2025 zhang alan. All rights reserved.
//
#import "GDWebPageHookService.h"
@implementation GDWebPageHookService
#pragma mark -
- (instancetype)initWithSchemeTask:(id<WKURLSchemeTask>)task {
if (self = [super init]) {
_schemeTask = task;
}
return self;
}
#pragma mark - GDWebCustomURLSchemeProtocol
+ (BOOL)canService:(id<WKURLSchemeTask>)task {
// "/api/hook"
NSString *urlString = task.request.URL.absoluteString;
return [urlString containsString:@"/api/hook"];
}
- (void)startLoading:(void (^)(void))completion {
self.completion = completion;
NSURLRequest *request = self.schemeTask.request;
// 1.
self.dataTask = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error) {
//
[self.schemeTask didFailWithError:error];
if (completion) completion();
return;
}
// 2. API
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSMutableDictionary *headers = [httpResponse.allHeaderFields mutableCopy];
//
headers[@"Access-Control-Allow-Origin"] = @"*";
// JSON
NSData *modifiedData = data;
if ([httpResponse.MIMEType containsString:@"application/json"] && data) {
NSMutableDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
if (json) {
json[@"_injected_by_native"] = @"true"; //
modifiedData = [NSJSONSerialization dataWithJSONObject:json options:0 error:nil];
}
}
// 3.
NSHTTPURLResponse *modifiedResponse = [[NSHTTPURLResponse alloc] initWithURL:httpResponse.URL
statusCode:httpResponse.statusCode
HTTPVersion:@"HTTP/1.1"
headerFields:headers];
[self.schemeTask didReceiveResponse:modifiedResponse];
[self.schemeTask didReceiveData:modifiedData];
[self.schemeTask didFinish];
//
if (completion) completion();
}];
[self.dataTask resume];
}
- (void)stopLoading {
//
[self.dataTask cancel];
self.dataTask = nil;
self.schemeTask = nil;
if (self.completion) self.completion();
}
@end

View File

@@ -0,0 +1,22 @@
//
// GDWebURLSchemeHandler.h
// DESThreeTest
//
// Created by Qwerdf on 2025/10/24.
// Copyright © 2025 zhang alan. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <WebKit/WebKit.h>
#import "GDWebCustomURLSchemeProtocol.h"
NS_ASSUME_NONNULL_BEGIN
@interface GDWebURLSchemeHandler : NSObject<WKURLSchemeHandler>
@property (nonatomic, strong) NSMutableDictionary *tasks;
@property (nonatomic, strong) NSMutableDictionary *schemeStatusDic;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,51 @@
//
// GDWebURLSchemeHandler.m
// DESThreeTest
//
// Created by Qwerdf on 2025/10/24.
// Copyright © 2025 zhang alan. All rights reserved.
//
#import "GDWebURLSchemeHandler.h"
#import "GDWebAssetStorageService.h"
#import "GDWebPageHookService.h"
#import "GDWebURLSessionService.h"
@implementation GDWebURLSchemeHandler
- (instancetype)init {
_tasks = [NSMutableDictionary dictionary];
_schemeStatusDic = [NSMutableDictionary dictionary];
return self;
}
- (void)webView: (WKWebView *)webView startURLSchemeTask: (id<WKURLSchemeTask>)urlSchemeTask {
id<GDWebCustomURLSchemeProtocol> service;
if ([GDWebAssetStorageService canService:urlSchemeTask]) {
service = [[GDWebAssetStorageService alloc] initWithSchemeTask:urlSchemeTask];
}else if ([GDWebPageHookService canService:urlSchemeTask]) {
service = [[GDWebPageHookService alloc] initWithSchemeTask:urlSchemeTask];
}else {
service = [[GDWebURLSessionService alloc] initWithSchemeTask:urlSchemeTask];
GDWebURLSessionService *webService = (GDWebURLSessionService *)service;
webService.stopMarkDic = self.schemeStatusDic;
}
[self.tasks setValue:service forKey:urlSchemeTask.description];
[service startLoading:^{
// GDStrongify(self);
[self.tasks removeObjectForKey:urlSchemeTask.description];
}];
}
- (void)webView: (WKWebView *)webView stopURLSchemeTask: (id<WKURLSchemeTask>)urlSchemeTask {
[self.schemeStatusDic setObject:@1 forKey:urlSchemeTask.description];
NSURL *URL = urlSchemeTask.request.URL;
id<GDWebCustomURLSchemeProtocol> service = self.tasks[URL.absoluteString];
[service stopLoading];
[self.tasks removeObjectForKey:urlSchemeTask.description];
}
@end

View File

@@ -0,0 +1,28 @@
//
// GDWebURLSessionDelegate.h
// DESThreeTest
//
// Created by Qwerdf on 2025/10/24.
// Copyright © 2025 zhang alan. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <WebKit/WebKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface GDWebURLSessionDelegate : NSObject <NSURLSessionDataDelegate>
@property (nonatomic, strong) id<WKURLSchemeTask> schemeTask;
@property (nonatomic, copy) void(^completion)(void);
@property (nonatomic, weak) NSMutableDictionary *stopMarkDic;
@property (nonatomic, strong) NSURLResponse *cachedResponse; // 缓存响应头
@property (nonatomic, strong) NSMutableData *cachedData; // 缓存响应体数据
/// 初始化:关联 schemeTask 和完成回调
- (instancetype)initWithSchemeTask:(id<WKURLSchemeTask>)schemeTask
completion:(void(^)(void))completion;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,323 @@
//
// GDWebURLSessionDelegate.m
// DESThreeTest
//
// Created by Qwerdf on 2025/10/24.
// Copyright © 2025 zhang alan. All rights reserved.
//
#import "GDWebURLSessionDelegate.h"
#import "MacroDefine.h"
@implementation GDWebURLSessionDelegate
- (instancetype)initWithSchemeTask:(id<WKURLSchemeTask>)schemeTask
completion:(void(^)(void))completion {
if (self = [super init]) {
_schemeTask = schemeTask;
_completion = completion;
_cachedData = [NSMutableData data]; //
}
return self;
}
#pragma mark - NSURLSessionDataDelegate
// 1.
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response newRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLRequest * _Nullable))completionHandler {
NSURL *url = response.URL;
if (url.pathExtension.length == 0 || [url.pathExtension isEqualToString:@"html"]) {
// HTML , nil, dataTaskWithRequest code = 302 response, webview 302
completionHandler(nil);
} else {
completionHandler(request);
}
}
// 2.
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSHTTPURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler {
self.cachedResponse = response; //
if (!self.stopMarkDic[_schemeTask.description]) {
@try {
[self.schemeTask didReceiveResponse:response];
} @catch (NSException *exception) {
}
}
completionHandler(NSURLSessionResponseAllow);
}
// 3.
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
[self.cachedData appendData:data]; //
if (!self.stopMarkDic[_schemeTask.description]) {
@try {
[self.schemeTask didReceiveData:data];
} @catch (NSException *exception) {
}
}
}
// 4. /
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
@try {
if (self.stopMarkDic[_schemeTask.description]) {
[self.stopMarkDic removeObjectForKey:_schemeTask.description];
} else {
if (error) {
[_schemeTask didFailWithError:error];
} else {
[_schemeTask didFinish];
[self handleSuccessResult:self.cachedResponse data:self.cachedData];
}
}
} @catch (NSException *exception) {
}
//
if (self.completion) self.completion();
}
//
- (void)handleSuccessResult:(NSURLResponse *)response data:(NSData *)data {
NSURLRequest *request = self.schemeTask.request;
NSURL *url = request.URL;
NSString *httpMethod = request.HTTPMethod ?: @"GET"; // GET
// ===== 1. =====
// NSLog(@"请求 URL%@", url.absoluteString);
// NSLog(@"请求方法:%@", httpMethod);
// NSLog(@"请求头:%@", request.allHTTPHeaderFields);
// ===== 2. URL GET =====
NSString *queryString = url.query;
if (queryString.length > 0) {
NSDictionary *queryParams = [self parseQueryString:queryString];
// NSLog(@"GET 参数:%@", queryParams);
}
NSDictionary *postParams = [NSDictionary dictionary];
// ===== 3. POST =====
if ([httpMethod.uppercaseString isEqualToString:@"POST"] && request.HTTPBody) {
// 3.1 application/x-www-form-urlencoded
NSString *postBodyString = [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding];
if (postBodyString) {
// Content-Type
NSString *contentType = request.allHTTPHeaderFields[@"Content-Type"];
if ([contentType containsString:@"application/x-www-form-urlencoded"]) {
postParams = [self parseQueryString:postBodyString];
// NSLog(@"POST 表单参数:%@", postParams);
}
// 3.2 JSON application/json
else if ([contentType containsString:@"application/json"]) {
NSError *jsonError;
id jsonObject = [NSJSONSerialization JSONObjectWithData:request.HTTPBody options:0 error:&jsonError];
if (jsonObject && !jsonError) {
// NSLog(@"POST JSON 参数:%@", jsonObject);
} else {
// NSLog(@"POST JSON 解析失败:%@,原始数据:%@", jsonError, postBodyString);
}
}
// 3.3 multipart/form-data
else {
NSString *contentTypeStr = request.allHTTPHeaderFields[@"Content-Type"];
NSString *boundaryStr = nil;
// 1. "boundary="
NSArray *components = [contentType componentsSeparatedByString:@"boundary="];
if (components.count >= 2) {
// 2. boundary
boundaryStr = [components[1] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
}
postParams = [self parseFormData:request.HTTPBody boundary:boundaryStr];
// NSLog(@"POST 其他格式数据:%@", postBodyString);
}
}
}
NSDictionary *jsonDic = [NSDictionary dictionary];
// JSON
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if (httpResponse.statusCode == 200) { // 200
NSError *jsonError;
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
if (json && !jsonError) {
jsonDic = json;
}
}
}
[self uploadDataWithRequest:postParams backDic:jsonDic url:url.absoluteString];
}
- (void)uploadDataWithRequest:(NSDictionary *)parameter backDic:(NSDictionary *)backDic url:(NSString *)url {
// /merchants/getPublicInfo accessToken merchantIdID module
// users/login mobile
if (backDic == nil) {
return;
}
// NSLog(@"-------%@:%@,%@",parameter,backDic,url);
if (![backDic isKindOfClass:[NSDictionary class]]) {
return;
}
id status = backDic[@"status"];
BOOL isSuccess = NO;
if ([status isKindOfClass:[NSString class]]) {
if ([backDic[@"status"] isEqualToString:@"SUCCESS"]) {
isSuccess = YES;
}
}else if ([status isKindOfClass:[NSNumber class]]) {
isSuccess = [backDic[@"status"] boolValue];
}
if (isSuccess) {
BOOL isLoginUrl = NO;
if ([url containsString:@"validateUserJs"]) {
isLoginUrl = YES;
}
NSString *moduleStr = parameter[@"module"];
if (!ISNULLSTR(moduleStr)) {
if ([moduleStr containsString:@"users/login"]) {
isLoginUrl = YES;
}
}
if (isLoginUrl) {
NSString *mobileStr = parameter[@"mobile"];
if (ISNULLSTR(mobileStr)) {
mobileStr = parameter[@"login_id"];
}
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:updataLoginUser]];
request.HTTPMethod = @"POST";
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
NSDictionary *parmas = @{@"phone":mobileStr,@"appId":NowUserId};
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:parmas options:NSJSONWritingPrettyPrinted error:nil];
request.HTTPBody = jsonData;
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
}];
[dataTask resume];
}
}
}
// "key1=value1&key2=value2"
- (NSDictionary *)parseQueryString:(NSString *)queryString {
if (!queryString || queryString.length == 0) {
return @{};
}
NSMutableDictionary *params = [NSMutableDictionary dictionary];
NSArray *pairs = [queryString componentsSeparatedByString:@"&"];
for (NSString *pair in pairs) {
// key value = key=value=123
NSRange equalRange = [pair rangeOfString:@"="];
if (equalRange.location == NSNotFound) {
// = key
NSString *key = [pair stringByRemovingPercentEncoding];
params[key] = @"";
continue;
}
NSString *key = [pair substringToIndex:equalRange.location];
NSString *value = [pair substringFromIndex:equalRange.location + 1];
// URL %20
key = [key stringByRemovingPercentEncoding];
value = [value stringByRemovingPercentEncoding];
if (key) {
params[key] = value ?: @"";
}
}
return params;
}
- (NSDictionary<NSString *, NSString *> *)parseFormData:(NSData *)data boundary:(NSString *)boundary {
//
if (!data || data.length == 0 || !boundary || boundary.length == 0) {
NSLog(@"无效的表单数据或边界符");
return nil;
}
// 1. UTF-8
NSString *content = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if (!content) {
NSLog(@"表单数据编码转换失败(非 UTF-8");
return nil;
}
// 2. multipart "--"
NSString *fullBoundary = [NSString stringWithFormat:@"--%@", boundary];
// --boundary--
NSArray *parts = [content componentsSeparatedByString:fullBoundary];
NSMutableArray *validParts = [NSMutableArray array];
for (NSString *part in parts) {
//
NSString *trimmedPart = [part stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if (trimmedPart.length > 0 && ![trimmedPart isEqualToString:@"--"]) { //
[validParts addObject:trimmedPart];
}
}
// 3. name
NSMutableDictionary *resultDict = [NSMutableDictionary dictionary];
for (NSString *part in validParts) {
//
// Content-Disposition: form-data; name="login_id"\r\n
// \r\n
// 11
// "\r\n\r\n"
NSArray *partComponents = [part componentsSeparatedByString:@"\r\n\r\n"];
if (partComponents.count < 2) {
continue; //
}
// 3.1 name Content-Disposition
NSString *dispositionLine = partComponents[0]; // "Content-Disposition: form-data; name="login_id""
NSString *name = [self extractNameFromDisposition:dispositionLine];
if (!name) {
continue; // name
}
// 3.2
NSString *value = partComponents[1];
value = [value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
// 3.3
resultDict[name] = value;
}
return resultDict.count > 0 ? [resultDict copy] : nil;
}
/// Content-Disposition name
/// @param disposition "Content-Disposition: form-data; name="login_id""
/// @return name "login_id"
- (NSString *)extractNameFromDisposition:(NSString *)disposition {
if (!disposition) return nil;
// name="xxx" xxx
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"name=\"([^\"]+)\""
options:0
error:nil];
NSTextCheckingResult *match = [regex firstMatchInString:disposition
options:0
range:NSMakeRange(0, disposition.length)];
if (match && match.numberOfRanges > 1) {
NSRange nameRange = [match rangeAtIndex:1];
return [disposition substringWithRange:nameRange];
}
return nil;
}
@end

View File

@@ -0,0 +1,23 @@
//
// GDWebURLSessionService.h
// DESThreeTest
//
// Created by Qwerdf on 2025/10/24.
// Copyright © 2025 zhang alan. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "GDWebCustomURLSchemeProtocol.h"
NS_ASSUME_NONNULL_BEGIN
@interface GDWebURLSessionService : NSObject <GDWebCustomURLSchemeProtocol>
@property (nonatomic, strong) id<WKURLSchemeTask> schemeTask;
@property (nonatomic, copy) void(^completion)(void);
@property (nonatomic, strong) NSURLSessionDataTask *dataTask;
@property (nonatomic, weak) NSMutableDictionary *stopMarkDic;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,69 @@
//
// GDWebURLSessionService.m
// DESThreeTest
//
// Created by Qwerdf on 2025/10/24.
// Copyright © 2025 zhang alan. All rights reserved.
//
#import "GDWebURLSessionService.h"
#import "GDWebURLSessionDelegate.h"
@implementation GDWebURLSessionService
#pragma mark -
- (instancetype)initWithSchemeTask:(id<WKURLSchemeTask>)task {
if (self = [super init]) {
_schemeTask = task;
}
return self;
}
#pragma mark - GDWebCustomURLSchemeProtocol
+ (BOOL)canService:(id<WKURLSchemeTask>)task {
//
return YES;
}
- (void)startLoading:(void (^)(void))completion {
self.completion = completion;
NSURLRequest *request = self.schemeTask.request;
//
// self.dataTask = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
// if (error) {
// [self.schemeTask didFailWithError:error];
// } else {
// [self.schemeTask didReceiveResponse:response];
// if (data) [self.schemeTask didReceiveData:data];
// [self.schemeTask didFinish];
// }
// if (completion) completion();
// }];
// [self.dataTask resume];
// ===== NSURLSession + =====
// Cookie
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
// schemeTask
GDWebURLSessionDelegate *sessionDelegate = [[GDWebURLSessionDelegate alloc] initWithSchemeTask:self.schemeTask completion:completion];
sessionDelegate.stopMarkDic = self.stopMarkDic; // dic
// delegateQueue nil
NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:sessionDelegate delegateQueue:nil];
// sharedSession dataTask
self.dataTask = [session dataTaskWithRequest:request];
[self.dataTask resume];
}
- (void)stopLoading {
[self.dataTask cancel];
self.dataTask = nil;
self.schemeTask = nil;
if (self.completion) self.completion();
}
@end

View File

@@ -0,0 +1,19 @@
//
// GameWebViewController.h
// ShenQi
//
// Created by Qwerdf on 2025/11/11.
//
#import <UIKit/UIKit.h>
#import <WebKit/WebKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface GameWebViewController : UIViewController
@property (nonatomic, strong) WKWebViewConfiguration *gameConfiguration;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,38 @@
//
// GameWebViewController.m
// ShenQi
//
// Created by Qwerdf on 2025/11/11.
//
#import "GameWebViewController.h"
@interface GameWebViewController ()<WKUIDelegate,WKNavigationDelegate>
@property (strong, nonatomic) WKWebView *webView;
@property (nonatomic,strong) WKUserContentController *wkUController;
@end
@implementation GameWebViewController
- (void)viewDidLoad {
[super viewDidLoad];
WKWebViewConfiguration *wkWebConfig = [[WKWebViewConfiguration alloc] init];
wkWebConfig.preferences.javaScriptCanOpenWindowsAutomatically = YES;
_wkUController = [[WKUserContentController alloc] init];
wkWebConfig.userContentController = _wkUController;
UIStatusBarManager *statusBarManager = [UIApplication sharedApplication].windows.lastObject.windowScene.statusBarManager;
_webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, statusBarManager.statusBarFrame.size.height, self.view.bounds.size.width, self.view.bounds.size.height-self.view.safeAreaInsets.bottom-statusBarManager.statusBarFrame.size.height) configuration:self.gameConfiguration];
_webView.UIDelegate = self;
_webView.navigationDelegate = self;
[self.view addSubview:_webView];
}
@end

View File

@@ -3,17 +3,17 @@
<plist version="1.0">
<dict>
<key>API_KEY</key>
<string>AIzaSyBzxoVTlQF1Q7XEFqWAiS9dIFEZkcFk-o0</string>
<string>AIzaSyCRrTj7LNAjqb7mT8VAiF2SzvsSUwKjVB4</string>
<key>GCM_SENDER_ID</key>
<string>989163327252</string>
<string>875434561984</string>
<key>PLIST_VERSION</key>
<string>1</string>
<key>BUNDLE_ID</key>
<string>noti.OKEGO</string>
<string>noti.NO1VA9SG4</string>
<key>PROJECT_ID</key>
<string>okego-a50f6</string>
<string>nosgs-409e1</string>
<key>STORAGE_BUCKET</key>
<string>okego-a50f6.firebasestorage.app</string>
<string>nosgs-409e1.firebasestorage.app</string>
<key>IS_ADS_ENABLED</key>
<false></false>
<key>IS_ANALYTICS_ENABLED</key>
@@ -25,6 +25,6 @@
<key>IS_SIGNIN_ENABLED</key>
<true></true>
<key>GOOGLE_APP_ID</key>
<string>1:989163327252:ios:f5e39cecd23cd49a567c01</string>
<string>1:875434561984:ios:7a5199d245be0be58d3825</string>
</dict>
</plist>

View File

@@ -34,14 +34,20 @@
[self setupGameURLData];
}
-(void)intoMainWebView
{
UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
MainOldViewController *webViewController = [sb instantiateViewControllerWithIdentifier:@"MainOldViewController"];
webViewController.mainURLString = self.mainURLString;
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
appDelegate.mainURLString = self.mainURLString;
appDelegate.window.rootViewController = webViewController;
-(void)intoMainWebView:(NSString *)backupDomains {
//
NSArray *textArr = [backupDomains componentsSeparatedByString:@","];
[self getAccessibleDomain:self.mainURLString backupDomains:textArr completion:^(NSString *accessibleDomain) {
dispatch_async(dispatch_get_main_queue(), ^{
self.mainURLString = accessibleDomain;
UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
MainOldViewController *webViewController = [sb instantiateViewControllerWithIdentifier:@"MainOldViewController"];
webViewController.mainURLString = self.mainURLString;
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
appDelegate.mainURLString = self.mainURLString;
appDelegate.window.rootViewController = webViewController;
});
}];
}
-(void)setupGameURLData
@@ -81,8 +87,9 @@
self.mainURLString = [datadic objectForKey:@"url"];
self.mainURLString = [self.mainURLString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSString *backupDomains = [datadic objectForKey:@"backupDomains"];
if (!ISNULLSTR(self.mainURLString)) {
[self intoMainWebView];
[self intoMainWebView:backupDomains];
}
}else{
dispatch_async(dispatch_get_main_queue(), ^{
@@ -131,4 +138,84 @@
}
}
- (void)checkDomainAccessibility:(NSString *)domain completion:(void(^)(BOOL isAccessible))completion {
NSString *urlString = domain;
NSURL *url = [NSURL URLWithString:urlString];
NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
BOOL isAccessible = NO;
if (error) {
//
NSLog(@"Domain %@ is not reachable: %@", domain, error.localizedDescription);
} else {
//
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if (httpResponse.statusCode == 200) {
isAccessible = YES;
} else {
NSLog(@"Domain %@ returned status code: %ld", domain, (long)httpResponse.statusCode);
}
}
// 访
if (completion) {
completion(isAccessible);
}
}];
[task resume];
}
#pragma mark -
- (void)getAccessibleDomain:(NSString *)primaryDomain backupDomains:(NSArray<NSString *> *)backupDomains completion:(void(^)(NSString *accessibleDomain))completion {
if (ISNULLARRAY(backupDomains)) {
if (completion) {
completion(primaryDomain);
}
return;
}
//
[self checkDomainAccessibility:primaryDomain completion:^(BOOL isAccessible) {
if (isAccessible) {
// 访
if (completion) {
completion(primaryDomain);
}
} else {
// 访
__block NSString *reachableDomain = nil;
dispatch_group_t group = dispatch_group_create();
//
for (NSString *backupDomain in backupDomains) {
dispatch_group_enter(group);
[self checkDomainAccessibility:backupDomain completion:^(BOOL isAccessible) {
if (isAccessible && !reachableDomain) {
reachableDomain = backupDomain;
}
dispatch_group_leave(group);
}];
}
//
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 访
if (reachableDomain) {
if (completion) {
completion(reachableDomain);
}
} else {
// 访
if (completion) {
completion(primaryDomain);
}
}
});
}
}];
}
@end

View File

@@ -29,6 +29,8 @@
#define PushRecordsURL [NSString stringWithFormat:@"%@/api/push/pushRecords",BASEURL] // 推送中心
#define updataLoginUser [NSString stringWithFormat:@"%@/app/loginUser",BASEURL]
#define TESTUserID @"2"
@@ -163,7 +165,7 @@
#define AUKING777UserID @"186"
#define PXP99auUserID @"187"
#define OKEGOUserID @"188"
#define KONGBO96UserID @"189"
@@ -180,6 +182,7 @@
#define Scr66myUserID @"21"
#define WE88UserID @"22"
#define Gey99UserID @"23"
#define HariharispinUserID @"25"
#define DatojudiUserID @"26"
#define KakislotUserID @"27"
#define Shell96UserID @"28"
@@ -225,7 +228,7 @@
#define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width
#define SCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height
#define NowUserId OKEGOUserID
#define NowUserId @"220"
#endif /* MacroDefine_h */

View File

@@ -7,6 +7,7 @@
#import "MainOldViewController.h"
#import <Contacts/Contacts.h>
#import <WebKit/WebKit.h>
#import <SVProgressHUD.h>
@@ -22,6 +23,8 @@
#import "LinkConfig.h"
#import "NotiCenterViewController.h"
#import "GDWebURLSchemeHandler.h"
#import "GameWebViewController.h"
@interface MainOldViewController () <WKUIDelegate,WKNavigationDelegate,DSWebMenuDelegate>
@@ -32,6 +35,7 @@
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *dragHeightConstarint;
@property (weak, nonatomic) IBOutlet DSWebMenuCollectionView *webMenuCollectionView;
@property (nonatomic, strong) UIView *subBgView;
//@property (nonatomic, copy) NSString *redirectUrl;
@end
@@ -52,6 +56,7 @@
WKWebViewConfiguration *wkWebConfig = [[WKWebViewConfiguration alloc] init];
wkWebConfig.preferences.javaScriptCanOpenWindowsAutomatically = YES;
// [wkWebConfig setURLSchemeHandler:[GDWebURLSchemeHandler new] forURLScheme:@"https"];
_wkUController = [[WKUserContentController alloc] init];
@@ -63,18 +68,29 @@
_webView.navigationDelegate = self;
[self.view addSubview:_webView];
self.subBgView = [[UIView alloc] initWithFrame:self.view.frame];
self.subBgView = [[UIView alloc] init];
self.subBgView.backgroundColor = [UIColor whiteColor];
self.subBgView.hidden = YES;
[self.view addSubview:self.subBgView];
self.subBgView.translatesAutoresizingMaskIntoConstraints = NO;
// 0
NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:self.subBgView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];
NSLayoutConstraint *left = [NSLayoutConstraint constraintWithItem:self.subBgView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0];
NSLayoutConstraint *right = [NSLayoutConstraint constraintWithItem:self.subBgView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0];
NSLayoutConstraint *bottom = [NSLayoutConstraint constraintWithItem:self.subBgView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0];
[self.view addConstraints:@[top, left, right, bottom]];
NSMutableArray *menuArray = @[].mutableCopy;
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
NSInteger height = 0 ;
if (self.isPresent != YES) {
// if (self.isPresent != YES) {
//
height = 60;
[menuArray addObject:[NSNumber numberWithInteger:DSWebMenuHomeType]];
// height = 60;
// [menuArray addObject:[NSNumber numberWithInteger:DSWebMenuHomeType]];
//
height = height + 60;
LinkConfig *config = [[LinkConfig alloc] init];
@@ -84,47 +100,39 @@
config.linkUrl = appDelegate.mainURLString;
[menuArray addObject:config];
// height = height + 70;
//
// LinkConfig *config2 = [[LinkConfig alloc] init];
// config2.isGoBack = NO;
// config2.icon = @"missav2";
// config2.name = @"missav2";
// config2.linkUrl = @"https://zh.xhamster.com";
// [menuArray addObject:config2];
//
if (!ISNULLSTR(appDelegate.data.linkConfig)) {
NSError *jsonError;
id linkConfigResponse = [NSJSONSerialization JSONObjectWithData:[appDelegate.data.linkConfig dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error:&jsonError];
if (jsonError==nil && [linkConfigResponse isKindOfClass:[NSArray class]]) {
NSArray *linkConfigArray = linkConfigResponse;
height = height + linkConfigArray.count*70;
for (NSDictionary *dic in linkConfigArray) {
LinkConfig *linkModel = [LinkConfig modelWithDictionary:dic];
[menuArray addObject:linkModel];
}
}
}
// if (!ISNULLSTR(appDelegate.data.linkConfig)) {
// NSError *jsonError;
// id linkConfigResponse = [NSJSONSerialization JSONObjectWithData:[appDelegate.data.linkConfig dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error:&jsonError];
// if (jsonError==nil && [linkConfigResponse isKindOfClass:[NSArray class]]) {
// NSArray *linkConfigArray = linkConfigResponse;
// height = height + linkConfigArray.count*70;
// for (NSDictionary *dic in linkConfigArray) {
// LinkConfig *linkModel = [LinkConfig modelWithDictionary:dic];
// [menuArray addObject:linkModel];
// }
// }
// }
//
if (!ISNULLSTR(appDelegate.data.fbUrl)) {
height = height + 70;
[menuArray addObject:[NSNumber numberWithInteger:DSWebMenuFacebookType]];
}
if (!ISNULLSTR(appDelegate.data.tgUrl)) {
height = height + 70;
[menuArray addObject:[NSNumber numberWithInteger:DSWebMenuTelegramType]];
}
if (!ISNULLSTR(appDelegate.data.wsUrl)) {
height = height + 70;
[menuArray addObject:[NSNumber numberWithInteger:DSWebMenuWhatsAppType]];
}
// if (!ISNULLSTR(appDelegate.data.fbUrl)) {
// height = height + 70;
// [menuArray addObject:[NSNumber numberWithInteger:DSWebMenuFacebookType]];
// }
// if (!ISNULLSTR(appDelegate.data.tgUrl)) {
// height = height + 70;
// [menuArray addObject:[NSNumber numberWithInteger:DSWebMenuTelegramType]];
// }
// if (!ISNULLSTR(appDelegate.data.wsUrl)) {
// height = height + 70;
// [menuArray addObject:[NSNumber numberWithInteger:DSWebMenuWhatsAppType]];
// }
//
height = height + 70;
[menuArray addObject:[NSNumber numberWithInteger:DSWebMenuRefreshType]];
// height = height + 70;
// [menuArray addObject:[NSNumber numberWithInteger:DSWebMenuRefreshType]];
//
height = height + 70;
[menuArray addObject:[NSNumber numberWithInteger:DSWebMenuNotiType]];
}
// }
self.webMenuCollectionView.shareArray = menuArray;
self.webMenuCollectionView.webMenuDelegate = self;
@@ -143,8 +151,8 @@
if (self.isPresent == YES) {
[self dismissViewControllerAnimated:YES completion:^{}];
}else{
self.webDragView.hidden = YES;
self.webMenuCollectionView.hidden = NO;
// self.webDragView.hidden = YES;
// self.webMenuCollectionView.hidden = NO;
}
};
@@ -229,8 +237,8 @@
[self presentViewController:notiCenterViewController animated:NO completion:nil];
}
}
self.webDragView.hidden = NO;
self.webMenuCollectionView.hidden = YES;
// self.webDragView.hidden = NO;
// self.webMenuCollectionView.hidden = YES;
}
-(void)intoMainWebView
@@ -261,6 +269,17 @@
newWebView.UIDelegate = self;
newWebView.navigationDelegate = self;
[self.subBgView addSubview:newWebView];
newWebView.translatesAutoresizingMaskIntoConstraints = NO;
// 0
NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:newWebView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.subBgView attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];
NSLayoutConstraint *left = [NSLayoutConstraint constraintWithItem:newWebView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.subBgView attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0];
NSLayoutConstraint *right = [NSLayoutConstraint constraintWithItem:newWebView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.subBgView attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0];
NSLayoutConstraint *bottom = [NSLayoutConstraint constraintWithItem:newWebView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.subBgView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0];
[self.subBgView addConstraints:@[top, left, right, bottom]];
return newWebView;
}else if (navigationAction.request.URL) {
@@ -272,7 +291,10 @@
view.isPresent = YES;
view.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentViewController:view animated:YES completion:^{}];
[view.view bringSubviewToFront:self.webMenuCollectionView];
}
[self.view bringSubviewToFront:self.webMenuCollectionView];
return nil;
}

View File

@@ -0,0 +1,17 @@
//
// WKWebView+GDWebURLSchemeHandler.h
// DESThreeTest
//
// Created by Qwerdf on 2025/10/24.
// Copyright © 2025 zhang alan. All rights reserved.
//
#import <WebKit/WebKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface WKWebView (GDWebURLSchemeHandler)
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,32 @@
//
// WKWebView+GDWebURLSchemeHandler.m
// DESThreeTest
//
// Created by Qwerdf on 2025/10/24.
// Copyright © 2025 zhang alan. All rights reserved.
//
#import "WKWebView+GDWebURLSchemeHandler.h"
#import <objc/runtime.h>
@implementation WKWebView (GDWebURLSchemeHandler)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Method originalMethod = class_getClassMethod(self, @selector(handlesURLScheme:));
Method swizzledMethod = class_getClassMethod(self, @selector(gd_handlesURLScheme:));
method_exchangeImplementations(originalMethod, swizzledMethod);
});
}
+ (BOOL)gd_handlesURLScheme:(NSString *)urlScheme {
if ([urlScheme isEqualToString:@"https"]) {
return NO;
} else {
return [self handlesURLScheme:urlScheme];
}
}
@end