image switch address
This commit is contained in:
parent
caef949f32
commit
c95771e637
|
@ -24,7 +24,8 @@ import (
|
|||
|
||||
func InitClient() {
|
||||
client.Timeout = time.Second * 60
|
||||
switchAddress, _ = properties.LoadSwitchAddress()
|
||||
switchAddress, _ = properties.LoadIntProperty("switchAddress", 1)
|
||||
imageSwitchAddress, _ = properties.LoadIntProperty("imageSwitchAddress", 1)
|
||||
proxy, _ := properties.LoadProxy()
|
||||
changeProxyUrl(proxy)
|
||||
}
|
||||
|
@ -36,15 +37,18 @@ var dialer = &net.Dialer{
|
|||
}
|
||||
|
||||
// SwitchAddress
|
||||
// addr = "172.67.7.24:443"
|
||||
// addr = "104.20.180.50:443"
|
||||
// addr = "172.67.208.169:443"
|
||||
var switchAddress = ""
|
||||
var switchAddressPattern, _ = regexp.Compile("^.+picacomic\\.com:\\d+$")
|
||||
var switchAddresses = map[int]string{
|
||||
1: "172.67.7.24:443",
|
||||
2: "104.20.180.50:443",
|
||||
3: "172.67.208.169:443",
|
||||
}
|
||||
|
||||
var switchAddress = 1
|
||||
var switchAddressPattern, _ = regexp.Compile("^.+pica" + "comic\\.com:\\d+$")
|
||||
|
||||
func switchAddressContext(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
if switchAddressPattern.MatchString(addr) && switchAddress != "" {
|
||||
addr = switchAddress
|
||||
if sAddr, ok := switchAddresses[switchAddress]; ok {
|
||||
addr = sAddr
|
||||
}
|
||||
return dialer.DialContext(ctx, network, addr)
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package controller
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
_ "golang.org/x/image/webp"
|
||||
"image"
|
||||
|
@ -9,20 +10,46 @@ import (
|
|||
_ "image/jpeg"
|
||||
_ "image/png"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"pikapika/main/database/comic_center"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var mutexCounter = -1
|
||||
var busMutex *sync.Mutex
|
||||
var subMutexes []*sync.Mutex
|
||||
var imageHttpClient *http.Client
|
||||
|
||||
// imageSwitchAddress
|
||||
// 图片的分流直接使用 switchAddressPattern 可以正常使用
|
||||
// 通过ping发现图片的分流地址与ip一致
|
||||
// 这里为了域名与官方一致改为域名分流
|
||||
var imageSwitchAddresses = map[int]string{
|
||||
1: "https://storage.wika" + "wika.xyz",
|
||||
2: "https://s2.pica" + "comic.com",
|
||||
3: "https://s3.pica" + "comic.com",
|
||||
}
|
||||
|
||||
var imageSwitchAddress int
|
||||
|
||||
func init() {
|
||||
busMutex = &sync.Mutex{}
|
||||
for i := 0; i < 5; i++ {
|
||||
subMutexes = append(subMutexes, &sync.Mutex{})
|
||||
}
|
||||
imageHttpClient = &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSHandshakeTimeout: time.Second * 10,
|
||||
ExpectContinueTimeout: time.Second * 10,
|
||||
ResponseHeaderTimeout: time.Second * 10,
|
||||
IdleConnTimeout: time.Second * 10,
|
||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
return dialer.DialContext(ctx, network, addr)
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// takeMutex 下载图片获取一个锁, 这样只能同时下载5张图片
|
||||
|
@ -52,6 +79,13 @@ func decodeFromFile(path string) ([]byte, image.Image, string, error) {
|
|||
|
||||
// 下载图片并decode
|
||||
func decodeFromUrl(fileServer string, path string) ([]byte, image.Image, string, error) {
|
||||
useClient := imageHttpClient
|
||||
if imageSwitchAddress == -1 {
|
||||
useClient = &client.Client
|
||||
}
|
||||
if server, ok := imageSwitchAddresses[imageSwitchAddress]; ok {
|
||||
fileServer = server
|
||||
}
|
||||
m := takeMutex()
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
@ -59,7 +93,7 @@ func decodeFromUrl(fileServer string, path string) ([]byte, image.Image, string,
|
|||
if err != nil {
|
||||
return nil, nil, "", err
|
||||
}
|
||||
response, err := client.Do(request)
|
||||
response, err := useClient.Do(request)
|
||||
if err != nil {
|
||||
return nil, nil, "", err
|
||||
}
|
||||
|
|
|
@ -100,16 +100,37 @@ func loadDownloadThreadCount() int {
|
|||
}
|
||||
|
||||
func setSwitchAddress(nSwitchAddress string) error {
|
||||
err := properties.SaveSwitchAddress(nSwitchAddress)
|
||||
num, err := strconv.Atoi(nSwitchAddress)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switchAddress = nSwitchAddress
|
||||
err = properties.SaveIntProperty("switchAddress", num)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switchAddress = num
|
||||
return nil
|
||||
}
|
||||
|
||||
func getSwitchAddress() (string, error) {
|
||||
return switchAddress, nil
|
||||
return strconv.Itoa(switchAddress), nil
|
||||
}
|
||||
|
||||
func setImageSwitchAddress(nSwitchAddress string) error {
|
||||
num, err := strconv.Atoi(nSwitchAddress)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = properties.SaveIntProperty("imageSwitchAddress", num)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switchAddress = num
|
||||
return nil
|
||||
}
|
||||
|
||||
func getImageSwitchAddress() (string, error) {
|
||||
return strconv.Itoa(imageSwitchAddress), nil
|
||||
}
|
||||
|
||||
func setProxy(value string) error {
|
||||
|
@ -534,6 +555,10 @@ func FlatInvoke(method string, params string) (string, error) {
|
|||
return "", setSwitchAddress(params)
|
||||
case "getSwitchAddress":
|
||||
return getSwitchAddress()
|
||||
case "setImageSwitchAddress":
|
||||
return "", setImageSwitchAddress(params)
|
||||
case "getImageSwitchAddress":
|
||||
return getImageSwitchAddress()
|
||||
case "setProxy":
|
||||
return "", setProxy(params)
|
||||
case "getProxy":
|
||||
|
|
|
@ -2,6 +2,7 @@ package properties
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
|
@ -65,18 +66,22 @@ func LoadBoolProperty(name string, defaultValue bool) (bool, error) {
|
|||
return strconv.ParseBool(stringValue)
|
||||
}
|
||||
|
||||
func LoadIntProperty(name string, defaultValue int) (int, error) {
|
||||
str, err := LoadProperty(name, fmt.Sprintf("%d", defaultValue))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return strconv.Atoi(str)
|
||||
}
|
||||
|
||||
func SaveIntProperty(name string, value int) error {
|
||||
return SaveProperty(name, strconv.Itoa(value))
|
||||
}
|
||||
|
||||
func SaveBoolProperty(name string, value bool) error {
|
||||
return SaveProperty(name, strconv.FormatBool(value))
|
||||
}
|
||||
|
||||
func SaveSwitchAddress(value string) error {
|
||||
return SaveProperty("switch_address", value)
|
||||
}
|
||||
|
||||
func LoadSwitchAddress() (string, error) {
|
||||
return LoadProperty("switch_address", "")
|
||||
}
|
||||
|
||||
func SaveProxy(value string) error {
|
||||
return SaveProperty("proxy", value)
|
||||
}
|
||||
|
|
|
@ -50,6 +50,16 @@ class Method {
|
|||
return await _flatInvoke("setSwitchAddress", switchAddress);
|
||||
}
|
||||
|
||||
/// 获取当前的图片分流
|
||||
Future<String> getImageSwitchAddress() async {
|
||||
return await _flatInvoke("getImageSwitchAddress", "");
|
||||
}
|
||||
|
||||
/// 更换图片分流
|
||||
Future<dynamic> setImageSwitchAddress(String switchAddress) async {
|
||||
return await _flatInvoke("setImageSwitchAddress", switchAddress);
|
||||
}
|
||||
|
||||
/// 获取代理
|
||||
Future<String> getProxy() async {
|
||||
return await _flatInvoke("getProxy", "");
|
||||
|
|
|
@ -9,10 +9,10 @@ import 'package:flutter/material.dart';
|
|||
import '../Method.dart';
|
||||
|
||||
var _addresses = {
|
||||
"不分流": "",
|
||||
"分流1": "172.67.7.24:443",
|
||||
"分流2": "104.20.180.50:443",
|
||||
"分流3": "72.67.208.169:443",
|
||||
"0": "不分流",
|
||||
"1": "分流1 (推荐)",
|
||||
"2": "分流2",
|
||||
"3": "分流3",
|
||||
};
|
||||
|
||||
late String _currentAddress;
|
||||
|
@ -21,16 +21,11 @@ Future<void> initAddress() async {
|
|||
_currentAddress = await method.getSwitchAddress();
|
||||
}
|
||||
|
||||
String currentAddressName() {
|
||||
for (var value in _addresses.entries) {
|
||||
if (value.value == _currentAddress) {
|
||||
return value.key;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
String _currentAddressName() {
|
||||
return _addresses[_currentAddress] ?? "";
|
||||
}
|
||||
|
||||
Future<void> chooseAddress(BuildContext context) async {
|
||||
Future<void> _chooseAddress(BuildContext context) async {
|
||||
String? choose = await showDialog<String>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
|
@ -39,9 +34,9 @@ Future<void> chooseAddress(BuildContext context) async {
|
|||
children: <Widget>[
|
||||
..._addresses.entries.map(
|
||||
(e) => SimpleDialogOption(
|
||||
child: Text(e.key),
|
||||
child: Text(e.value),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(e.value);
|
||||
Navigator.of(context).pop(e.key);
|
||||
},
|
||||
),
|
||||
),
|
||||
|
@ -54,3 +49,18 @@ Future<void> chooseAddress(BuildContext context) async {
|
|||
_currentAddress = choose;
|
||||
}
|
||||
}
|
||||
|
||||
Widget switchAddressSetting() {
|
||||
return StatefulBuilder(
|
||||
builder: (BuildContext context, void Function(void Function()) setState) {
|
||||
return ListTile(
|
||||
title: Text("分流"),
|
||||
subtitle: Text(_currentAddressName()),
|
||||
onTap: () async {
|
||||
await _chooseAddress(context);
|
||||
setState(() {});
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../Method.dart';
|
||||
|
||||
var _imageAddresses = {
|
||||
"-1": "跟随api分流",
|
||||
"0": "不分流",
|
||||
"1": "分流1 (推荐)",
|
||||
"2": "分流2",
|
||||
"3": "分流3",
|
||||
};
|
||||
|
||||
late String _currentImageAddress;
|
||||
|
||||
Future<void> initImageAddress() async {
|
||||
_currentImageAddress = await method.getImageSwitchAddress();
|
||||
}
|
||||
|
||||
String _currentImageAddressName() {
|
||||
return _imageAddresses[_currentImageAddress] ?? "";
|
||||
}
|
||||
|
||||
Future<void> _chooseImageAddress(BuildContext context) async {
|
||||
String? choose = await showDialog<String>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return SimpleDialog(
|
||||
title: Text('选择图片分流'),
|
||||
children: <Widget>[
|
||||
..._imageAddresses.entries.map(
|
||||
(e) => SimpleDialogOption(
|
||||
child: Text(e.value),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(e.key);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
if (choose != null) {
|
||||
await method.setImageSwitchAddress(choose);
|
||||
_currentImageAddress = choose;
|
||||
}
|
||||
}
|
||||
|
||||
Widget imageSwitchAddressSetting() {
|
||||
return StatefulBuilder(
|
||||
builder: (BuildContext context, void Function(void Function()) setState) {
|
||||
return ListTile(
|
||||
title: Text("图片"),
|
||||
subtitle: Text(_currentImageAddressName()),
|
||||
onTap: () async {
|
||||
await _chooseImageAddress(context);
|
||||
setState(() {});
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
|
@ -28,3 +28,18 @@ Future<dynamic> inputProxy(BuildContext context) async {
|
|||
_currentProxy = input;
|
||||
}
|
||||
}
|
||||
|
||||
Widget proxySetting() {
|
||||
return StatefulBuilder(
|
||||
builder: (BuildContext context, void Function(void Function()) setState) {
|
||||
return ListTile(
|
||||
title: Text("代理服务器"),
|
||||
subtitle: Text(currentProxyName()),
|
||||
onTap: () async {
|
||||
await inputProxy(context);
|
||||
setState(() {});
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -6,17 +6,17 @@ import 'package:pikapika/basic/Navigatior.dart';
|
|||
import 'basic/config/Themes.dart';
|
||||
|
||||
void main() {
|
||||
runApp(PikapiApp());
|
||||
runApp(PikapikaApp());
|
||||
}
|
||||
|
||||
class PikapiApp extends StatefulWidget {
|
||||
const PikapiApp({Key? key}) : super(key: key);
|
||||
class PikapikaApp extends StatefulWidget {
|
||||
const PikapikaApp({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _PikapiAppState();
|
||||
State<StatefulWidget> createState() => _PikapikaAppState();
|
||||
}
|
||||
|
||||
class _PikapiAppState extends State<PikapiApp> {
|
||||
class _PikapikaAppState extends State<PikapikaApp> {
|
||||
@override
|
||||
void initState() {
|
||||
themeEvent.subscribe(_onChangeTheme);
|
||||
|
|
|
@ -11,6 +11,7 @@ import 'package:pikapika/basic/config/DownloadAndExportPath.dart';
|
|||
import 'package:pikapika/basic/config/DownloadThreadCount.dart';
|
||||
import 'package:pikapika/basic/config/FullScreenAction.dart';
|
||||
import 'package:pikapika/basic/config/FullScreenUI.dart';
|
||||
import 'package:pikapika/basic/config/ImageAddress.dart';
|
||||
import 'package:pikapika/basic/config/KeyboardController.dart';
|
||||
import 'package:pikapika/basic/config/NoAnimation.dart';
|
||||
import 'package:pikapika/basic/config/PagerAction.dart';
|
||||
|
@ -49,6 +50,7 @@ class _InitScreenState extends State<InitScreen> {
|
|||
await initPlatform(); // 必须第一个初始化, 加载设备信息
|
||||
await initAutoClean();
|
||||
await initAddress();
|
||||
await initImageAddress();
|
||||
await initProxy();
|
||||
await initQuality();
|
||||
await initFont();
|
||||
|
|
|
@ -220,7 +220,7 @@ class _RemoteImageState extends State<RemoteImage> {
|
|||
|
||||
@override
|
||||
void initState() {
|
||||
_mock = widget.fileServer == "" || widget.fileServer.contains(".xyz/");
|
||||
_mock = widget.fileServer == "";
|
||||
if (!_mock) {
|
||||
_future = method
|
||||
.remoteImageData(widget.fileServer, widget.path)
|
||||
|
|
|
@ -1,35 +1,18 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:pikapika/basic/config/Address.dart';
|
||||
import 'package:pikapika/basic/config/ImageAddress.dart';
|
||||
import 'package:pikapika/basic/config/Proxy.dart';
|
||||
|
||||
// 网络设置
|
||||
class NetworkSetting extends StatefulWidget {
|
||||
@override
|
||||
State<StatefulWidget> createState() => _NetworkSettingState();
|
||||
}
|
||||
|
||||
class _NetworkSettingState extends State<NetworkSetting> {
|
||||
class NetworkSetting extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
title: Text("分流"),
|
||||
subtitle: Text(currentAddressName()),
|
||||
onTap: () async {
|
||||
await chooseAddress(context);
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: Text("代理服务器"),
|
||||
subtitle: Text(currentProxyName()),
|
||||
onTap: () async {
|
||||
await inputProxy(context);
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
switchAddressSetting(),
|
||||
imageSwitchAddressSetting(),
|
||||
proxySetting(),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
|
@ -13,7 +13,7 @@ import 'package:pikapika/main.dart';
|
|||
void main() {
|
||||
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
||||
// Build our app and trigger a frame.
|
||||
await tester.pumpWidget(PikapiApp());
|
||||
await tester.pumpWidget(PikapikaApp());
|
||||
|
||||
// Verify that our counter starts at 0.
|
||||
expect(find.text('0'), findsOneWidget);
|
||||
|
|
Loading…
Reference in New Issue