Compare commits
1 Commits
v0.8.83-pr
...
v0.8.83-pr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7cb5d40969 |
1
.github/workflows/build.yaml
vendored
1
.github/workflows/build.yaml
vendored
@@ -201,6 +201,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
|
TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
|
||||||
TAG: ${{ github.ref_name }}
|
TAG: ${{ github.ref_name }}
|
||||||
|
RUN_ID: ${{ github.run_id }}
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install requests
|
pip install requests
|
||||||
|
|||||||
@@ -391,5 +391,6 @@
|
|||||||
"messageTest": "Message test",
|
"messageTest": "Message test",
|
||||||
"messageTestTip": "This is a message.",
|
"messageTestTip": "This is a message.",
|
||||||
"crashTest": "Crash test",
|
"crashTest": "Crash test",
|
||||||
"clearData": "Clear Data"
|
"clearData": "Clear Data",
|
||||||
|
"textScale": "Text Scaling"
|
||||||
}
|
}
|
||||||
@@ -391,5 +391,7 @@
|
|||||||
"messageTest": "メッセージテスト",
|
"messageTest": "メッセージテスト",
|
||||||
"messageTestTip": "これはメッセージです。",
|
"messageTestTip": "これはメッセージです。",
|
||||||
"crashTest": "クラッシュテスト",
|
"crashTest": "クラッシュテスト",
|
||||||
"clearData": "データを消去"
|
"clearData": "データを消去",
|
||||||
|
"zoom": "ズーム",
|
||||||
|
"textScale": "テキストスケーリング"
|
||||||
}
|
}
|
||||||
@@ -391,5 +391,7 @@
|
|||||||
"messageTest": "Тестирование сообщения",
|
"messageTest": "Тестирование сообщения",
|
||||||
"messageTestTip": "Это сообщение.",
|
"messageTestTip": "Это сообщение.",
|
||||||
"crashTest": "Тест на сбои",
|
"crashTest": "Тест на сбои",
|
||||||
"clearData": "Очистить данные"
|
"clearData": "Очистить данные",
|
||||||
|
"zoom": "Масштаб",
|
||||||
|
"textScale": "Масштабирование текста"
|
||||||
}
|
}
|
||||||
@@ -391,5 +391,7 @@
|
|||||||
"messageTest": "消息测试",
|
"messageTest": "消息测试",
|
||||||
"messageTestTip": "这是一条消息。",
|
"messageTestTip": "这是一条消息。",
|
||||||
"crashTest": "崩溃测试",
|
"crashTest": "崩溃测试",
|
||||||
"clearData": "清除数据"
|
"clearData": "清除数据",
|
||||||
|
"zoom": "缩放",
|
||||||
|
"textScale": "文本缩放"
|
||||||
}
|
}
|
||||||
@@ -17,15 +17,12 @@ const packageName = "com.follow.clash";
|
|||||||
final unixSocketPath = "/tmp/FlClashSocket_${Random().nextInt(10000)}.sock";
|
final unixSocketPath = "/tmp/FlClashSocket_${Random().nextInt(10000)}.sock";
|
||||||
const helperPort = 47890;
|
const helperPort = 47890;
|
||||||
const helperTag = "2024125";
|
const helperTag = "2024125";
|
||||||
const baseInfoEdgeInsets = EdgeInsets.symmetric(
|
final baseInfoEdgeInsets = EdgeInsets.symmetric(
|
||||||
vertical: 16,
|
vertical: 16.ap,
|
||||||
horizontal: 16,
|
horizontal: 16.ap,
|
||||||
);
|
);
|
||||||
|
|
||||||
double textScaleFactor = min(
|
final defaultTextScaleFactor = WidgetsBinding.instance.platformDispatcher.textScaleFactor;
|
||||||
WidgetsBinding.instance.platformDispatcher.textScaleFactor,
|
|
||||||
1.2,
|
|
||||||
);
|
|
||||||
const httpTimeoutDuration = Duration(milliseconds: 5000);
|
const httpTimeoutDuration = Duration(milliseconds: 5000);
|
||||||
const moreDuration = Duration(milliseconds: 100);
|
const moreDuration = Duration(milliseconds: 100);
|
||||||
const animateDuration = Duration(milliseconds: 100);
|
const animateDuration = Duration(milliseconds: 100);
|
||||||
@@ -44,7 +41,6 @@ const profilesDirectoryName = "profiles";
|
|||||||
const localhost = "127.0.0.1";
|
const localhost = "127.0.0.1";
|
||||||
const clashConfigKey = "clash_config";
|
const clashConfigKey = "clash_config";
|
||||||
const configKey = "config";
|
const configKey = "config";
|
||||||
const listItemPadding = EdgeInsets.symmetric(horizontal: 16);
|
|
||||||
const double dialogCommonWidth = 300;
|
const double dialogCommonWidth = 300;
|
||||||
const repository = "chen08209/FlClash";
|
const repository = "chen08209/FlClash";
|
||||||
const defaultExternalController = "127.0.0.1:9090";
|
const defaultExternalController = "127.0.0.1:9090";
|
||||||
@@ -81,7 +77,7 @@ const viewModeColumnsMap = {
|
|||||||
const defaultPrimaryColor = 0xFF795548;
|
const defaultPrimaryColor = 0xFF795548;
|
||||||
|
|
||||||
double getWidgetHeight(num lines) {
|
double getWidgetHeight(num lines) {
|
||||||
return max(lines * 84 * textScaleFactor + (lines - 1) * 16, 0);
|
return max(lines * 84 + (lines - 1) * 16, 0).ap;
|
||||||
}
|
}
|
||||||
|
|
||||||
final mainIsolate = "FlClashMainIsolate";
|
final mainIsolate = "FlClashMainIsolate";
|
||||||
|
|||||||
@@ -3,11 +3,13 @@ import 'package:flutter/cupertino.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class Measure {
|
class Measure {
|
||||||
final TextScaler _textScale;
|
final TextScaler _textScaler;
|
||||||
final BuildContext context;
|
final BuildContext context;
|
||||||
|
final Map<String, dynamic> _measureMap;
|
||||||
|
|
||||||
Measure.of(this.context)
|
Measure.of(this.context, double textScaleFactor)
|
||||||
: _textScale = TextScaler.linear(
|
: _measureMap = {},
|
||||||
|
_textScaler = TextScaler.linear(
|
||||||
textScaleFactor,
|
textScaleFactor,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -21,7 +23,7 @@ class Measure {
|
|||||||
style: text.style,
|
style: text.style,
|
||||||
),
|
),
|
||||||
maxLines: text.maxLines,
|
maxLines: text.maxLines,
|
||||||
textScaler: _textScale,
|
textScaler: _textScaler,
|
||||||
textDirection: text.textDirection ?? TextDirection.ltr,
|
textDirection: text.textDirection ?? TextDirection.ltr,
|
||||||
)..layout(
|
)..layout(
|
||||||
maxWidth: maxWidth,
|
maxWidth: maxWidth,
|
||||||
@@ -29,81 +31,75 @@ class Measure {
|
|||||||
return textPainter.size;
|
return textPainter.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
double? _bodyMediumHeight;
|
|
||||||
Size? _bodyLargeSize;
|
|
||||||
double? _bodySmallHeight;
|
|
||||||
double? _labelSmallHeight;
|
|
||||||
double? _labelMediumHeight;
|
|
||||||
double? _titleLargeHeight;
|
|
||||||
double? _titleMediumHeight;
|
|
||||||
|
|
||||||
double get bodyMediumHeight {
|
double get bodyMediumHeight {
|
||||||
_bodyMediumHeight ??= computeTextSize(
|
return _measureMap.getCacheValue(
|
||||||
Text(
|
"bodyMediumHeight",
|
||||||
"X",
|
computeTextSize(
|
||||||
style: context.textTheme.bodyMedium,
|
Text(
|
||||||
),
|
"X",
|
||||||
).height;
|
style: context.textTheme.bodyMedium,
|
||||||
return _bodyMediumHeight!;
|
),
|
||||||
}
|
).height,
|
||||||
|
|
||||||
Size get bodyLargeSize {
|
|
||||||
_bodyLargeSize ??= computeTextSize(
|
|
||||||
Text(
|
|
||||||
"X",
|
|
||||||
style: context.textTheme.bodyLarge,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
return _bodyLargeSize!;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double get bodySmallHeight {
|
double get bodySmallHeight {
|
||||||
_bodySmallHeight ??= computeTextSize(
|
return _measureMap.getCacheValue(
|
||||||
Text(
|
"bodySmallHeight",
|
||||||
"X",
|
computeTextSize(
|
||||||
style: context.textTheme.bodySmall,
|
Text(
|
||||||
),
|
"X",
|
||||||
).height;
|
style: context.textTheme.bodySmall,
|
||||||
return _bodySmallHeight!;
|
),
|
||||||
|
).height,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
double get labelSmallHeight {
|
double get labelSmallHeight {
|
||||||
_labelSmallHeight ??= computeTextSize(
|
return _measureMap.getCacheValue(
|
||||||
Text(
|
"labelSmallHeight",
|
||||||
"X",
|
computeTextSize(
|
||||||
style: context.textTheme.labelSmall,
|
Text(
|
||||||
),
|
"X",
|
||||||
).height;
|
style: context.textTheme.labelSmall,
|
||||||
return _labelSmallHeight!;
|
),
|
||||||
|
).height,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
double get labelMediumHeight {
|
double get labelMediumHeight {
|
||||||
_labelMediumHeight ??= computeTextSize(
|
return _measureMap.getCacheValue(
|
||||||
Text(
|
"labelMediumHeight",
|
||||||
"X",
|
computeTextSize(
|
||||||
style: context.textTheme.labelMedium,
|
Text(
|
||||||
),
|
"X",
|
||||||
).height;
|
style: context.textTheme.labelMedium,
|
||||||
return _labelMediumHeight!;
|
),
|
||||||
|
).height,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
double get titleLargeHeight {
|
double get titleLargeHeight {
|
||||||
_titleLargeHeight ??= computeTextSize(
|
return _measureMap.getCacheValue(
|
||||||
Text(
|
"titleLargeHeight",
|
||||||
"X",
|
computeTextSize(
|
||||||
style: context.textTheme.titleLarge,
|
Text(
|
||||||
),
|
"X",
|
||||||
).height;
|
style: context.textTheme.titleLarge,
|
||||||
return _titleLargeHeight!;
|
),
|
||||||
|
).height,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
double get titleMediumHeight {
|
double get titleMediumHeight {
|
||||||
_titleMediumHeight ??= computeTextSize(
|
return _measureMap.getCacheValue(
|
||||||
Text(
|
"titleMediumHeight",
|
||||||
"X",
|
computeTextSize(
|
||||||
style: context.textTheme.titleMedium,
|
Text(
|
||||||
),
|
"X",
|
||||||
).height;
|
style: context.textTheme.titleMedium,
|
||||||
return _titleMediumHeight!;
|
),
|
||||||
|
).height,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:fl_clash/state.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
@@ -12,6 +13,10 @@ extension NumExt on num {
|
|||||||
}
|
}
|
||||||
return formatted;
|
return formatted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double get ap {
|
||||||
|
return this * (1 + (globalState.theme.textScaleFactor - 1) * 0.5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension DoubleExt on double {
|
extension DoubleExt on double {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import 'package:fl_clash/enum/enum.dart';
|
|
||||||
import 'package:fl_clash/models/models.dart';
|
import 'package:fl_clash/models/models.dart';
|
||||||
import 'package:fl_clash/state.dart';
|
import 'package:fl_clash/state.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
@@ -20,10 +19,7 @@ class CommonPrint {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
globalState.appController.addLog(
|
globalState.appController.addLog(
|
||||||
Log(
|
Log.app(payload),
|
||||||
logLevel: LogLevel.app,
|
|
||||||
payload: payload,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,12 @@ import 'package:flutter/material.dart';
|
|||||||
class CommonTheme {
|
class CommonTheme {
|
||||||
final BuildContext context;
|
final BuildContext context;
|
||||||
final Map<String, Color> _colorMap;
|
final Map<String, Color> _colorMap;
|
||||||
|
final double textScaleFactor;
|
||||||
|
|
||||||
CommonTheme.of(this.context) : _colorMap = {};
|
CommonTheme.of(
|
||||||
|
this.context,
|
||||||
|
this.textScaleFactor,
|
||||||
|
) : _colorMap = {};
|
||||||
|
|
||||||
Color get darkenSecondaryContainer {
|
Color get darkenSecondaryContainer {
|
||||||
return _colorMap.getCacheValue(
|
return _colorMap.getCacheValue(
|
||||||
|
|||||||
@@ -334,12 +334,7 @@ class AppController {
|
|||||||
try {
|
try {
|
||||||
await updateProfile(profile);
|
await updateProfile(profile);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
_ref.read(logsProvider.notifier).addLog(
|
commonPrint.log(e.toString());
|
||||||
Log(
|
|
||||||
logLevel: LogLevel.info,
|
|
||||||
payload: e.toString(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,6 @@ class _RequestsFragmentState extends ConsumerState<RequestsFragment>
|
|||||||
updateRequestsThrottler();
|
updateRequestsThrottler();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fireImmediately: true,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,72 +148,77 @@ class _RequestsFragmentState extends ConsumerState<RequestsFragment>
|
|||||||
_handleTryClearCache(constraints.maxWidth - 40 - (value ? 60 : 0));
|
_handleTryClearCache(constraints.maxWidth - 40 - (value ? 60 : 0));
|
||||||
return child!;
|
return child!;
|
||||||
},
|
},
|
||||||
child: ValueListenableBuilder<ConnectionsState>(
|
child: TextScaleNotification(
|
||||||
valueListenable: _requestsStateNotifier,
|
child: ValueListenableBuilder<ConnectionsState>(
|
||||||
builder: (_, state, __) {
|
valueListenable: _requestsStateNotifier,
|
||||||
final connections = state.list;
|
builder: (_, state, __) {
|
||||||
if (connections.isEmpty) {
|
final connections = state.list;
|
||||||
return NullStatus(
|
if (connections.isEmpty) {
|
||||||
label: appLocalizations.nullRequestsDesc,
|
return NullStatus(
|
||||||
);
|
label: appLocalizations.nullRequestsDesc,
|
||||||
}
|
);
|
||||||
final items = connections
|
}
|
||||||
.map<Widget>(
|
final items = connections
|
||||||
(connection) => ConnectionItem(
|
.map<Widget>(
|
||||||
key: Key(connection.id),
|
(connection) => ConnectionItem(
|
||||||
connection: connection,
|
key: Key(connection.id),
|
||||||
onClickKeyword: (value) {
|
connection: connection,
|
||||||
context.commonScaffoldState?.addKeyword(value);
|
onClickKeyword: (value) {
|
||||||
},
|
context.commonScaffoldState?.addKeyword(value);
|
||||||
),
|
},
|
||||||
)
|
),
|
||||||
.separated(
|
)
|
||||||
const Divider(
|
.separated(
|
||||||
height: 0,
|
const Divider(
|
||||||
),
|
height: 0,
|
||||||
)
|
),
|
||||||
.toList();
|
)
|
||||||
return Align(
|
.toList();
|
||||||
alignment: Alignment.topCenter,
|
return Align(
|
||||||
child: ScrollToEndBox(
|
alignment: Alignment.topCenter,
|
||||||
controller: _scrollController,
|
child: ScrollToEndBox(
|
||||||
cacheKey: _cacheKey,
|
|
||||||
dataSource: connections,
|
|
||||||
child: CommonScrollBar(
|
|
||||||
controller: _scrollController,
|
controller: _scrollController,
|
||||||
child: CacheItemExtentListView(
|
cacheKey: _cacheKey,
|
||||||
key: _key,
|
dataSource: connections,
|
||||||
reverse: true,
|
child: CommonScrollBar(
|
||||||
shrinkWrap: true,
|
|
||||||
physics: NextClampingScrollPhysics(),
|
|
||||||
controller: _scrollController,
|
controller: _scrollController,
|
||||||
itemExtentBuilder: (index) {
|
child: CacheItemExtentListView(
|
||||||
final widget = items[index];
|
key: _key,
|
||||||
if (widget.runtimeType == Divider) {
|
reverse: true,
|
||||||
return 0;
|
shrinkWrap: true,
|
||||||
}
|
physics: NextClampingScrollPhysics(),
|
||||||
final measure = globalState.measure;
|
controller: _scrollController,
|
||||||
final bodyMediumHeight = measure.bodyMediumHeight;
|
itemExtentBuilder: (index) {
|
||||||
final connection = connections[(index / 2).floor()];
|
final widget = items[index];
|
||||||
final height = _calcCacheHeight(connection);
|
if (widget.runtimeType == Divider) {
|
||||||
return height + bodyMediumHeight + 32;
|
return 0;
|
||||||
},
|
}
|
||||||
itemBuilder: (_, index) {
|
final measure = globalState.measure;
|
||||||
return items[index];
|
final bodyMediumHeight = measure.bodyMediumHeight;
|
||||||
},
|
final connection = connections[(index / 2).floor()];
|
||||||
itemCount: items.length,
|
final height = _calcCacheHeight(connection);
|
||||||
keyBuilder: (int index) {
|
return height + bodyMediumHeight + 32;
|
||||||
final widget = items[index];
|
},
|
||||||
if (widget.runtimeType == Divider) {
|
itemBuilder: (_, index) {
|
||||||
return "divider";
|
return items[index];
|
||||||
}
|
},
|
||||||
final connection = connections[(index / 2).floor()];
|
itemCount: items.length,
|
||||||
return connection.id;
|
keyBuilder: (int index) {
|
||||||
},
|
final widget = items[index];
|
||||||
|
if (widget.runtimeType == Divider) {
|
||||||
|
return "divider";
|
||||||
|
}
|
||||||
|
final connection = connections[(index / 2).floor()];
|
||||||
|
return connection.id;
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
},
|
||||||
|
),
|
||||||
|
onNotification: (_) {
|
||||||
|
_key.currentState?.clearCache();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -103,8 +103,8 @@ class _DashboardFragmentState extends ConsumerState<DashboardFragment>
|
|||||||
child: SuperGrid(
|
child: SuperGrid(
|
||||||
key: key,
|
key: key,
|
||||||
crossAxisCount: columns,
|
crossAxisCount: columns,
|
||||||
crossAxisSpacing: 16,
|
crossAxisSpacing: 16.ap,
|
||||||
mainAxisSpacing: 16,
|
mainAxisSpacing: 16.ap,
|
||||||
children: [
|
children: [
|
||||||
...dashboardState.dashboardWidgets
|
...dashboardState.dashboardWidgets
|
||||||
.where(
|
.where(
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import 'dart:io';
|
|||||||
import 'package:fl_clash/clash/clash.dart';
|
import 'package:fl_clash/clash/clash.dart';
|
||||||
import 'package:fl_clash/common/common.dart';
|
import 'package:fl_clash/common/common.dart';
|
||||||
import 'package:fl_clash/models/common.dart';
|
import 'package:fl_clash/models/common.dart';
|
||||||
|
import 'package:fl_clash/state.dart';
|
||||||
import 'package:fl_clash/widgets/widgets.dart';
|
import 'package:fl_clash/widgets/widgets.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
@@ -57,37 +58,43 @@ class _MemoryInfoState extends State<MemoryInfo> {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
clashCore.requestGc();
|
clashCore.requestGc();
|
||||||
},
|
},
|
||||||
child: Column(
|
child: Container(
|
||||||
children: [
|
padding: baseInfoEdgeInsets.copyWith(
|
||||||
ValueListenableBuilder(
|
top: 0,
|
||||||
valueListenable: _memoryInfoStateNotifier,
|
),
|
||||||
builder: (_, trafficValue, __) {
|
child: Column(
|
||||||
return Padding(
|
mainAxisSize: MainAxisSize.max,
|
||||||
padding: baseInfoEdgeInsets.copyWith(
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
bottom: 0,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
top: 12,
|
children: [
|
||||||
),
|
SizedBox(
|
||||||
child: Row(
|
height: globalState.measure.bodyMediumHeight + 2,
|
||||||
children: [
|
child: ValueListenableBuilder(
|
||||||
Text(
|
valueListenable: _memoryInfoStateNotifier,
|
||||||
trafficValue.showValue,
|
builder: (_, trafficValue, __) {
|
||||||
style:
|
return Row(
|
||||||
context.textTheme.bodyMedium?.toLight.adjustSize(1),
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
),
|
children: [
|
||||||
SizedBox(
|
Text(
|
||||||
width: 8,
|
trafficValue.showValue,
|
||||||
),
|
style: context.textTheme.bodyMedium?.toLight
|
||||||
Text(
|
.adjustSize(1),
|
||||||
trafficValue.showUnit,
|
),
|
||||||
style:
|
SizedBox(
|
||||||
context.textTheme.bodyMedium?.toLight.adjustSize(1),
|
width: 8,
|
||||||
)
|
),
|
||||||
],
|
Text(
|
||||||
),
|
trafficValue.showUnit,
|
||||||
);
|
style: context.textTheme.bodyMedium?.toLight
|
||||||
},
|
.adjustSize(1),
|
||||||
),
|
)
|
||||||
],
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ class _NetworkDetectionState extends ConsumerState<NetworkDetection> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
size: 16,
|
size: 16.ap,
|
||||||
Icons.info_outline,
|
Icons.info_outline,
|
||||||
color: context.colorScheme.onSurfaceVariant,
|
color: context.colorScheme.onSurfaceVariant,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -17,56 +17,66 @@ class OutboundMode extends StatelessWidget {
|
|||||||
height: height,
|
height: height,
|
||||||
child: Consumer(
|
child: Consumer(
|
||||||
builder: (_, ref, __) {
|
builder: (_, ref, __) {
|
||||||
final mode =
|
final mode = ref.watch(
|
||||||
ref.watch(patchClashConfigProvider.select((state) => state.mode));
|
patchClashConfigProvider.select(
|
||||||
return CommonCard(
|
(state) => state.mode,
|
||||||
onPressed: () {},
|
|
||||||
info: Info(
|
|
||||||
label: appLocalizations.outboundMode,
|
|
||||||
iconData: Icons.call_split_sharp,
|
|
||||||
),
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
top: 12,
|
|
||||||
bottom: 16,
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.max,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
for (final item in Mode.values)
|
|
||||||
Flexible(
|
|
||||||
child: ListItem.radio(
|
|
||||||
dense: true,
|
|
||||||
horizontalTitleGap: 4,
|
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
left: 12,
|
|
||||||
right: 16,
|
|
||||||
),
|
|
||||||
delegate: RadioDelegate(
|
|
||||||
value: item,
|
|
||||||
groupValue: mode,
|
|
||||||
onChanged: (value) async {
|
|
||||||
if (value == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
globalState.appController.changeMode(value);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
title: Text(
|
|
||||||
Intl.message(item.name),
|
|
||||||
style: Theme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.bodyMedium
|
|
||||||
?.toSoftBold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
return Theme(
|
||||||
|
data: Theme.of(context).copyWith(
|
||||||
|
splashColor: Colors.transparent,
|
||||||
|
highlightColor: Colors.transparent,
|
||||||
|
hoverColor: Colors.transparent
|
||||||
|
),
|
||||||
|
child: CommonCard(
|
||||||
|
onPressed: () {},
|
||||||
|
info: Info(
|
||||||
|
label: appLocalizations.outboundMode,
|
||||||
|
iconData: Icons.call_split_sharp,
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
top: 12,
|
||||||
|
bottom: 16,
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
for (final item in Mode.values)
|
||||||
|
Flexible(
|
||||||
|
fit: FlexFit.tight,
|
||||||
|
child: ListItem.radio(
|
||||||
|
dense: true,
|
||||||
|
horizontalTitleGap: 4,
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: 12.ap,
|
||||||
|
right: 16.ap,
|
||||||
|
),
|
||||||
|
delegate: RadioDelegate(
|
||||||
|
value: item,
|
||||||
|
groupValue: mode,
|
||||||
|
onChanged: (value) async {
|
||||||
|
if (value == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
globalState.appController.changeMode(value);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
Intl.message(item.name),
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodyMedium
|
||||||
|
?.toSoftBold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -76,12 +86,21 @@ class OutboundMode extends StatelessWidget {
|
|||||||
class OutboundModeV2 extends StatelessWidget {
|
class OutboundModeV2 extends StatelessWidget {
|
||||||
const OutboundModeV2({super.key});
|
const OutboundModeV2({super.key});
|
||||||
|
|
||||||
|
Color _getTextColor(BuildContext context, Mode mode) {
|
||||||
|
return switch (mode) {
|
||||||
|
Mode.rule => context.colorScheme.onSecondaryContainer,
|
||||||
|
Mode.global => context.colorScheme.onPrimaryContainer,
|
||||||
|
Mode.direct => context.colorScheme.onTertiaryContainer,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final height = getWidgetHeight(0.72);
|
final height = getWidgetHeight(0.72);
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: height,
|
height: height,
|
||||||
child: CommonCard(
|
child: CommonCard(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
child: Consumer(
|
child: Consumer(
|
||||||
builder: (_, ref, __) {
|
builder: (_, ref, __) {
|
||||||
final mode = ref.watch(
|
final mode = ref.watch(
|
||||||
@@ -102,14 +121,22 @@ class OutboundModeV2 extends StatelessWidget {
|
|||||||
(item) => MapEntry(
|
(item) => MapEntry(
|
||||||
item,
|
item,
|
||||||
Container(
|
Container(
|
||||||
|
clipBehavior: Clip.antiAlias,
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(),
|
||||||
height: height - 16,
|
height: height - 16,
|
||||||
child: Text(
|
child: Text(
|
||||||
Intl.message(item.name),
|
Intl.message(item.name),
|
||||||
style: Theme.of(context)
|
style: Theme.of(context)
|
||||||
.textTheme
|
.textTheme
|
||||||
.titleSmall
|
.titleSmall
|
||||||
?.adjustSize(1),
|
?.adjustSize(1)
|
||||||
|
.copyWith(
|
||||||
|
color: _getTextColor(
|
||||||
|
context,
|
||||||
|
mode,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -34,19 +34,6 @@ class _LogsFragmentState extends ConsumerState<LogsFragment> with PageMixin {
|
|||||||
_logsStateNotifier.value = _logsStateNotifier.value.copyWith(
|
_logsStateNotifier.value = _logsStateNotifier.value.copyWith(
|
||||||
logs: globalState.appState.logs.list,
|
logs: globalState.appState.logs.list,
|
||||||
);
|
);
|
||||||
ref.listenManual(
|
|
||||||
logsProvider.select((state) => state.list),
|
|
||||||
(prev, next) {
|
|
||||||
if (prev != next) {
|
|
||||||
final isEquality = logListEquality.equals(prev, next);
|
|
||||||
if (!isEquality) {
|
|
||||||
_logs = next;
|
|
||||||
updateLogsThrottler();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
fireImmediately: true,
|
|
||||||
);
|
|
||||||
ref.listenManual(
|
ref.listenManual(
|
||||||
isCurrentPageProvider(
|
isCurrentPageProvider(
|
||||||
PageLabel.logs,
|
PageLabel.logs,
|
||||||
@@ -60,6 +47,18 @@ class _LogsFragmentState extends ConsumerState<LogsFragment> with PageMixin {
|
|||||||
},
|
},
|
||||||
fireImmediately: true,
|
fireImmediately: true,
|
||||||
);
|
);
|
||||||
|
ref.listenManual(
|
||||||
|
logsProvider.select((state) => state.list),
|
||||||
|
(prev, next) {
|
||||||
|
if (prev != next) {
|
||||||
|
final isEquality = logListEquality.equals(prev, next);
|
||||||
|
if (!isEquality) {
|
||||||
|
_logs = next;
|
||||||
|
updateLogsThrottler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -123,7 +122,7 @@ class _LogsFragmentState extends ConsumerState<LogsFragment> with PageMixin {
|
|||||||
final height = globalState.measure
|
final height = globalState.measure
|
||||||
.computeTextSize(
|
.computeTextSize(
|
||||||
Text(
|
Text(
|
||||||
log.payload ?? "",
|
log.payload,
|
||||||
style: globalState.appController.context.textTheme.bodyLarge,
|
style: globalState.appController.context.textTheme.bodyLarge,
|
||||||
),
|
),
|
||||||
maxWidth: _currentMaxWidth,
|
maxWidth: _currentMaxWidth,
|
||||||
@@ -154,8 +153,7 @@ class _LogsFragmentState extends ConsumerState<LogsFragment> with PageMixin {
|
|||||||
return LayoutBuilder(
|
return LayoutBuilder(
|
||||||
builder: (_, constraints) {
|
builder: (_, constraints) {
|
||||||
_handleTryClearCache(constraints.maxWidth - 40);
|
_handleTryClearCache(constraints.maxWidth - 40);
|
||||||
return Align(
|
return TextScaleNotification(
|
||||||
alignment: Alignment.topCenter,
|
|
||||||
child: ValueListenableBuilder<LogsState>(
|
child: ValueListenableBuilder<LogsState>(
|
||||||
valueListenable: _logsStateNotifier,
|
valueListenable: _logsStateNotifier,
|
||||||
builder: (_, state, __) {
|
builder: (_, state, __) {
|
||||||
@@ -168,7 +166,7 @@ class _LogsFragmentState extends ConsumerState<LogsFragment> with PageMixin {
|
|||||||
final items = logs
|
final items = logs
|
||||||
.map<Widget>(
|
.map<Widget>(
|
||||||
(log) => LogItem(
|
(log) => LogItem(
|
||||||
key: Key(log.dateTime.toString()),
|
key: Key(log.dateTime),
|
||||||
log: log,
|
log: log,
|
||||||
onClick: (value) {
|
onClick: (value) {
|
||||||
context.commonScaffoldState?.addKeyword(value);
|
context.commonScaffoldState?.addKeyword(value);
|
||||||
@@ -181,43 +179,49 @@ class _LogsFragmentState extends ConsumerState<LogsFragment> with PageMixin {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
.toList();
|
.toList();
|
||||||
return ScrollToEndBox<Log>(
|
return Align(
|
||||||
controller: _scrollController,
|
alignment: Alignment.topCenter,
|
||||||
cacheKey: _cacheKey,
|
child: ScrollToEndBox<Log>(
|
||||||
dataSource: logs,
|
|
||||||
child: CommonScrollBar(
|
|
||||||
controller: _scrollController,
|
controller: _scrollController,
|
||||||
child: CacheItemExtentListView(
|
cacheKey: _cacheKey,
|
||||||
key: _key,
|
dataSource: logs,
|
||||||
reverse: true,
|
child: CommonScrollBar(
|
||||||
shrinkWrap: true,
|
|
||||||
physics: NextClampingScrollPhysics(),
|
|
||||||
controller: _scrollController,
|
controller: _scrollController,
|
||||||
itemBuilder: (_, index) {
|
child: CacheItemExtentListView(
|
||||||
return items[index];
|
key: _key,
|
||||||
},
|
reverse: true,
|
||||||
itemExtentBuilder: (index) {
|
shrinkWrap: true,
|
||||||
final item = items[index];
|
physics: NextClampingScrollPhysics(),
|
||||||
if (item.runtimeType == Divider) {
|
controller: _scrollController,
|
||||||
return 0;
|
itemBuilder: (_, index) {
|
||||||
}
|
return items[index];
|
||||||
final log = logs[(index / 2).floor()];
|
},
|
||||||
return _getItemHeight(log);
|
itemExtentBuilder: (index) {
|
||||||
},
|
final item = items[index];
|
||||||
itemCount: items.length,
|
if (item.runtimeType == Divider) {
|
||||||
keyBuilder: (int index) {
|
return 0;
|
||||||
final item = items[index];
|
}
|
||||||
if (item.runtimeType == Divider) {
|
final log = logs[(index / 2).floor()];
|
||||||
return "divider";
|
return _getItemHeight(log);
|
||||||
}
|
},
|
||||||
final log = logs[(index / 2).floor()];
|
itemCount: items.length,
|
||||||
return log.payload ?? "";
|
keyBuilder: (int index) {
|
||||||
},
|
final item = items[index];
|
||||||
|
if (item.runtimeType == Divider) {
|
||||||
|
return "divider";
|
||||||
|
}
|
||||||
|
final log = logs[(index / 2).floor()];
|
||||||
|
return log.payload;
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
onNotification: (_) {
|
||||||
|
_key.currentState?.clearCache();
|
||||||
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -242,14 +246,14 @@ class LogItem extends StatelessWidget {
|
|||||||
vertical: 4,
|
vertical: 4,
|
||||||
),
|
),
|
||||||
title: SelectableText(
|
title: SelectableText(
|
||||||
log.payload ?? '',
|
log.payload,
|
||||||
style: context.textTheme.bodyLarge,
|
style: context.textTheme.bodyLarge,
|
||||||
),
|
),
|
||||||
subtitle: Column(
|
subtitle: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
SelectableText(
|
SelectableText(
|
||||||
"${log.dateTime}",
|
log.dateTime,
|
||||||
style: context.textTheme.bodySmall?.copyWith(
|
style: context.textTheme.bodySmall?.copyWith(
|
||||||
color: context.colorScheme.primary,
|
color: context.colorScheme.primary,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ class _OverrideProfileState extends State<OverrideProfile> {
|
|||||||
message: TextSpan(
|
message: TextSpan(
|
||||||
text: appLocalizations.saveTip,
|
text: appLocalizations.saveTip,
|
||||||
),
|
),
|
||||||
confirmText: appLocalizations.tip,
|
confirmText: appLocalizations.save,
|
||||||
);
|
);
|
||||||
if (res != true) {
|
if (res != true) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -39,7 +39,19 @@ class ThemeFragment extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SingleChildScrollView(child: ThemeColorsBox());
|
return SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
_ThemeModeItem(),
|
||||||
|
_PrimaryColorItem(),
|
||||||
|
_PrueBlackItem(),
|
||||||
|
_TextScaleFactorItem(),
|
||||||
|
const SizedBox(
|
||||||
|
height: 64,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,29 +87,6 @@ class ItemCard extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ThemeColorsBox extends ConsumerStatefulWidget {
|
|
||||||
const ThemeColorsBox({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
ConsumerState<ThemeColorsBox> createState() => _ThemeColorsBoxState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _ThemeColorsBoxState extends ConsumerState<ThemeColorsBox> {
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Column(
|
|
||||||
children: [
|
|
||||||
_ThemeModeItem(),
|
|
||||||
_PrimaryColorItem(),
|
|
||||||
_PrueBlackItem(),
|
|
||||||
const SizedBox(
|
|
||||||
height: 64,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _ThemeModeItem extends ConsumerWidget {
|
class _ThemeModeItem extends ConsumerWidget {
|
||||||
const _ThemeModeItem();
|
const _ThemeModeItem();
|
||||||
|
|
||||||
@@ -482,6 +471,77 @@ class _PrueBlackItem extends ConsumerWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _TextScaleFactorItem extends ConsumerWidget {
|
||||||
|
const _TextScaleFactorItem();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final textScale = ref.watch(
|
||||||
|
themeSettingProvider.select(
|
||||||
|
(state) => state.textScale,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
final String process =
|
||||||
|
"${((textScale.scale * 100) as double).round()}%";
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||||
|
child: ListItem.switchItem(
|
||||||
|
leading: Icon(
|
||||||
|
Icons.text_fields,
|
||||||
|
),
|
||||||
|
horizontalTitleGap: 12,
|
||||||
|
title: Text(
|
||||||
|
appLocalizations.textScale,
|
||||||
|
style: Theme.of(context).textTheme.titleSmall?.copyWith(
|
||||||
|
color: context.colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
delegate: SwitchDelegate(
|
||||||
|
value: textScale.enable,
|
||||||
|
onChanged: (value) {
|
||||||
|
ref.read(themeSettingProvider.notifier).updateState(
|
||||||
|
(state) => state.copyWith.textScale(
|
||||||
|
enable: value,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
DisabledMask(
|
||||||
|
status: !textScale.enable,
|
||||||
|
child: ActivateBox(
|
||||||
|
active: textScale.enable,
|
||||||
|
child: SliderTheme(
|
||||||
|
data: _SliderDefaultsM3(context),
|
||||||
|
child: Slider(
|
||||||
|
min: 0.8,
|
||||||
|
divisions: 8,
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 16,
|
||||||
|
),
|
||||||
|
max: 1.2,
|
||||||
|
label: process,
|
||||||
|
value: textScale.scale,
|
||||||
|
onChanged: (value) {
|
||||||
|
ref.read(themeSettingProvider.notifier).updateState(
|
||||||
|
(state) => state.copyWith.textScale(
|
||||||
|
scale: value,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class _PaletteDialog extends StatefulWidget {
|
class _PaletteDialog extends StatefulWidget {
|
||||||
const _PaletteDialog();
|
const _PaletteDialog();
|
||||||
|
|
||||||
@@ -544,3 +604,112 @@ class _PaletteDialogState extends State<_PaletteDialog> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _SliderDefaultsM3 extends SliderThemeData {
|
||||||
|
_SliderDefaultsM3(this.context) : super(trackHeight: 16.0);
|
||||||
|
|
||||||
|
final BuildContext context;
|
||||||
|
late final ColorScheme _colors = Theme.of(context).colorScheme;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color? get activeTrackColor => _colors.primary;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color? get inactiveTrackColor => _colors.secondaryContainer;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color? get secondaryActiveTrackColor => _colors.primary.withOpacity(0.54);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color? get disabledActiveTrackColor => _colors.onSurface.withOpacity(0.38);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color? get disabledInactiveTrackColor => _colors.onSurface.withOpacity(0.12);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color? get disabledSecondaryActiveTrackColor =>
|
||||||
|
_colors.onSurface.withOpacity(0.38);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color? get activeTickMarkColor => _colors.onPrimary.withOpacity(1.0);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color? get inactiveTickMarkColor =>
|
||||||
|
_colors.onSecondaryContainer.withOpacity(1.0);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color? get disabledActiveTickMarkColor => _colors.onInverseSurface;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color? get disabledInactiveTickMarkColor => _colors.onSurface;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color? get thumbColor => _colors.primary;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color? get disabledThumbColor => _colors.onSurface.withOpacity(0.38);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color? get overlayColor =>
|
||||||
|
WidgetStateColor.resolveWith((Set<WidgetState> states) {
|
||||||
|
if (states.contains(WidgetState.dragged)) {
|
||||||
|
return _colors.primary.withOpacity(0.1);
|
||||||
|
}
|
||||||
|
if (states.contains(WidgetState.hovered)) {
|
||||||
|
return _colors.primary.withOpacity(0.08);
|
||||||
|
}
|
||||||
|
if (states.contains(WidgetState.focused)) {
|
||||||
|
return _colors.primary.withOpacity(0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Colors.transparent;
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
TextStyle? get valueIndicatorTextStyle =>
|
||||||
|
Theme.of(context).textTheme.labelLarge!.copyWith(
|
||||||
|
color: _colors.onInverseSurface,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color? get valueIndicatorColor => _colors.inverseSurface;
|
||||||
|
|
||||||
|
@override
|
||||||
|
SliderComponentShape? get valueIndicatorShape =>
|
||||||
|
const RoundedRectSliderValueIndicatorShape();
|
||||||
|
|
||||||
|
@override
|
||||||
|
SliderComponentShape? get thumbShape => const HandleThumbShape();
|
||||||
|
|
||||||
|
@override
|
||||||
|
SliderTrackShape? get trackShape => const GappedSliderTrackShape();
|
||||||
|
|
||||||
|
@override
|
||||||
|
SliderComponentShape? get overlayShape => const RoundSliderOverlayShape();
|
||||||
|
|
||||||
|
@override
|
||||||
|
SliderTickMarkShape? get tickMarkShape =>
|
||||||
|
const RoundSliderTickMarkShape(tickMarkRadius: 4.0 / 2);
|
||||||
|
|
||||||
|
@override
|
||||||
|
WidgetStateProperty<Size?>? get thumbSize {
|
||||||
|
return WidgetStateProperty.resolveWith((Set<WidgetState> states) {
|
||||||
|
if (states.contains(WidgetState.disabled)) {
|
||||||
|
return const Size(4.0, 44.0);
|
||||||
|
}
|
||||||
|
if (states.contains(WidgetState.hovered)) {
|
||||||
|
return const Size(4.0, 44.0);
|
||||||
|
}
|
||||||
|
if (states.contains(WidgetState.focused)) {
|
||||||
|
return const Size(2.0, 44.0);
|
||||||
|
}
|
||||||
|
if (states.contains(WidgetState.pressed)) {
|
||||||
|
return const Size(2.0, 44.0);
|
||||||
|
}
|
||||||
|
return const Size(4.0, 44.0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
double? get trackGap => 6.0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -637,6 +637,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"Enabling it will allow TCP concurrency",
|
"Enabling it will allow TCP concurrency",
|
||||||
),
|
),
|
||||||
"testUrl": MessageLookupByLibrary.simpleMessage("Test url"),
|
"testUrl": MessageLookupByLibrary.simpleMessage("Test url"),
|
||||||
|
"textScale": MessageLookupByLibrary.simpleMessage("Text Scaling"),
|
||||||
"theme": MessageLookupByLibrary.simpleMessage("Theme"),
|
"theme": MessageLookupByLibrary.simpleMessage("Theme"),
|
||||||
"themeColor": MessageLookupByLibrary.simpleMessage("Theme color"),
|
"themeColor": MessageLookupByLibrary.simpleMessage("Theme color"),
|
||||||
"themeDesc": MessageLookupByLibrary.simpleMessage(
|
"themeDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
|
|||||||
@@ -471,6 +471,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"tcpConcurrent": MessageLookupByLibrary.simpleMessage("TCP並列処理"),
|
"tcpConcurrent": MessageLookupByLibrary.simpleMessage("TCP並列処理"),
|
||||||
"tcpConcurrentDesc": MessageLookupByLibrary.simpleMessage("TCP並列処理を許可"),
|
"tcpConcurrentDesc": MessageLookupByLibrary.simpleMessage("TCP並列処理を許可"),
|
||||||
"testUrl": MessageLookupByLibrary.simpleMessage("URLテスト"),
|
"testUrl": MessageLookupByLibrary.simpleMessage("URLテスト"),
|
||||||
|
"textScale": MessageLookupByLibrary.simpleMessage("テキストスケーリング"),
|
||||||
"theme": MessageLookupByLibrary.simpleMessage("テーマ"),
|
"theme": MessageLookupByLibrary.simpleMessage("テーマ"),
|
||||||
"themeColor": MessageLookupByLibrary.simpleMessage("テーマカラー"),
|
"themeColor": MessageLookupByLibrary.simpleMessage("テーマカラー"),
|
||||||
"themeDesc": MessageLookupByLibrary.simpleMessage("ダークモードの設定、色の調整"),
|
"themeDesc": MessageLookupByLibrary.simpleMessage("ダークモードの設定、色の調整"),
|
||||||
|
|||||||
@@ -675,6 +675,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"Включение позволит использовать параллелизм TCP",
|
"Включение позволит использовать параллелизм TCP",
|
||||||
),
|
),
|
||||||
"testUrl": MessageLookupByLibrary.simpleMessage("Тест URL"),
|
"testUrl": MessageLookupByLibrary.simpleMessage("Тест URL"),
|
||||||
|
"textScale": MessageLookupByLibrary.simpleMessage("Масштабирование текста"),
|
||||||
"theme": MessageLookupByLibrary.simpleMessage("Тема"),
|
"theme": MessageLookupByLibrary.simpleMessage("Тема"),
|
||||||
"themeColor": MessageLookupByLibrary.simpleMessage("Цвет темы"),
|
"themeColor": MessageLookupByLibrary.simpleMessage("Цвет темы"),
|
||||||
"themeDesc": MessageLookupByLibrary.simpleMessage(
|
"themeDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
|
|||||||
@@ -413,6 +413,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"tcpConcurrent": MessageLookupByLibrary.simpleMessage("TCP并发"),
|
"tcpConcurrent": MessageLookupByLibrary.simpleMessage("TCP并发"),
|
||||||
"tcpConcurrentDesc": MessageLookupByLibrary.simpleMessage("开启后允许TCP并发"),
|
"tcpConcurrentDesc": MessageLookupByLibrary.simpleMessage("开启后允许TCP并发"),
|
||||||
"testUrl": MessageLookupByLibrary.simpleMessage("测速链接"),
|
"testUrl": MessageLookupByLibrary.simpleMessage("测速链接"),
|
||||||
|
"textScale": MessageLookupByLibrary.simpleMessage("文本缩放"),
|
||||||
"theme": MessageLookupByLibrary.simpleMessage("主题"),
|
"theme": MessageLookupByLibrary.simpleMessage("主题"),
|
||||||
"themeColor": MessageLookupByLibrary.simpleMessage("主题色彩"),
|
"themeColor": MessageLookupByLibrary.simpleMessage("主题色彩"),
|
||||||
"themeDesc": MessageLookupByLibrary.simpleMessage("设置深色模式,调整色彩"),
|
"themeDesc": MessageLookupByLibrary.simpleMessage("设置深色模式,调整色彩"),
|
||||||
|
|||||||
@@ -3054,6 +3054,11 @@ class AppLocalizations {
|
|||||||
String get clearData {
|
String get clearData {
|
||||||
return Intl.message('Clear Data', name: 'clearData', desc: '', args: []);
|
return Intl.message('Clear Data', name: 'clearData', desc: '', args: []);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `Text Scaling`
|
||||||
|
String get textScale {
|
||||||
|
return Intl.message('Text Scaling', name: 'textScale', desc: '', args: []);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AppLocalizationDelegate extends LocalizationsDelegate<AppLocalizations> {
|
class AppLocalizationDelegate extends LocalizationsDelegate<AppLocalizations> {
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ class _ClashContainerState extends ConsumerState<ClashManager>
|
|||||||
void onLog(Log log) {
|
void onLog(Log log) {
|
||||||
ref.watch(logsProvider.notifier).addLog(log);
|
ref.watch(logsProvider.notifier).addLog(log);
|
||||||
if (log.logLevel == LogLevel.error) {
|
if (log.logLevel == LogLevel.error) {
|
||||||
globalState.showNotifier(log.payload ?? '');
|
globalState.showNotifier(log.payload);
|
||||||
}
|
}
|
||||||
super.onLog(log);
|
super.onLog(log);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
|
import 'dart:math';
|
||||||
import 'package:fl_clash/common/constant.dart';
|
import 'package:fl_clash/common/constant.dart';
|
||||||
import 'package:fl_clash/common/measure.dart';
|
import 'package:fl_clash/common/measure.dart';
|
||||||
import 'package:fl_clash/common/theme.dart';
|
import 'package:fl_clash/common/theme.dart';
|
||||||
|
import 'package:fl_clash/providers/config.dart';
|
||||||
import 'package:fl_clash/state.dart';
|
import 'package:fl_clash/state.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
class ThemeManager extends StatelessWidget {
|
class ThemeManager extends ConsumerWidget {
|
||||||
final Widget child;
|
final Widget child;
|
||||||
|
|
||||||
const ThemeManager({
|
const ThemeManager({
|
||||||
@@ -13,9 +16,20 @@ class ThemeManager extends StatelessWidget {
|
|||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context, ref) {
|
||||||
globalState.measure = Measure.of(context);
|
final textScale = ref.read(
|
||||||
globalState.theme = CommonTheme.of(context);
|
themeSettingProvider.select((state) => state.textScale),
|
||||||
|
);
|
||||||
|
final double textScaleFactor = max(
|
||||||
|
min(
|
||||||
|
textScale.enable ? textScale.scale : defaultTextScaleFactor,
|
||||||
|
1.2,
|
||||||
|
),
|
||||||
|
0.8,
|
||||||
|
);
|
||||||
|
|
||||||
|
globalState.measure = Measure.of(context, textScaleFactor);
|
||||||
|
globalState.theme = CommonTheme.of(context, textScaleFactor);
|
||||||
final padding = MediaQuery.of(context).padding;
|
final padding = MediaQuery.of(context).padding;
|
||||||
final height = MediaQuery.of(context).size.height;
|
final height = MediaQuery.of(context).size.height;
|
||||||
return MediaQuery(
|
return MediaQuery(
|
||||||
|
|||||||
@@ -84,33 +84,33 @@ extension ConnectionExt on Connection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonSerializable()
|
String _logDateTime(_) {
|
||||||
class Log {
|
return DateTime.now().toString();
|
||||||
@JsonKey(name: "LogLevel")
|
}
|
||||||
LogLevel logLevel;
|
|
||||||
@JsonKey(name: "Payload")
|
|
||||||
String? payload;
|
|
||||||
DateTime _dateTime;
|
|
||||||
|
|
||||||
Log({
|
// String _logId(_) {
|
||||||
required this.logLevel,
|
// return utils.id;
|
||||||
this.payload,
|
// }
|
||||||
}) : _dateTime = DateTime.now();
|
|
||||||
|
|
||||||
DateTime get dateTime => _dateTime;
|
@freezed
|
||||||
|
class Log with _$Log {
|
||||||
|
const factory Log({
|
||||||
|
@JsonKey(name: "LogLevel") @Default(LogLevel.app) LogLevel logLevel,
|
||||||
|
@JsonKey(name: "Payload") @Default("") String payload,
|
||||||
|
@JsonKey(fromJson: _logDateTime) required String dateTime,
|
||||||
|
}) = _Log;
|
||||||
|
|
||||||
factory Log.fromJson(Map<String, dynamic> json) {
|
factory Log.app(
|
||||||
return _$LogFromJson(json);
|
String payload,
|
||||||
|
) {
|
||||||
|
return Log(
|
||||||
|
payload: payload,
|
||||||
|
dateTime: _logDateTime(null),
|
||||||
|
// id: _logId(null),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
factory Log.fromJson(Map<String, Object?> json) => _$LogFromJson(json);
|
||||||
return _$LogToJson(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() {
|
|
||||||
return 'Log{logLevel: $logLevel, payload: $payload, dateTime: $dateTime}';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
@@ -127,11 +127,10 @@ extension LogsStateExt on LogsState {
|
|||||||
final lowQuery = query.toLowerCase();
|
final lowQuery = query.toLowerCase();
|
||||||
return logs.where(
|
return logs.where(
|
||||||
(log) {
|
(log) {
|
||||||
final payload = log.payload?.toLowerCase();
|
final payload = log.payload.toLowerCase();
|
||||||
final logLevelName = log.logLevel.name;
|
final logLevelName = log.logLevel.name;
|
||||||
return {logLevelName}.containsAll(keywords) &&
|
return {logLevelName}.containsAll(keywords) &&
|
||||||
((payload?.contains(lowQuery) ?? false) ||
|
((payload.contains(lowQuery)) || logLevelName.contains(lowQuery));
|
||||||
logLevelName.contains(lowQuery));
|
|
||||||
},
|
},
|
||||||
).toList();
|
).toList();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -173,6 +173,17 @@ class ProxiesStyle with _$ProxiesStyle {
|
|||||||
json == null ? defaultProxiesStyle : _$ProxiesStyleFromJson(json);
|
json == null ? defaultProxiesStyle : _$ProxiesStyleFromJson(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class TextScale with _$TextScale {
|
||||||
|
const factory TextScale({
|
||||||
|
@Default(false) enable,
|
||||||
|
@Default(1.0) scale,
|
||||||
|
}) = _TextScale;
|
||||||
|
|
||||||
|
factory TextScale.fromJson(Map<String, Object?> json) =>
|
||||||
|
_$TextScaleFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
class ThemeProps with _$ThemeProps {
|
class ThemeProps with _$ThemeProps {
|
||||||
const factory ThemeProps({
|
const factory ThemeProps({
|
||||||
@@ -181,6 +192,7 @@ class ThemeProps with _$ThemeProps {
|
|||||||
@Default(ThemeMode.dark) ThemeMode themeMode,
|
@Default(ThemeMode.dark) ThemeMode themeMode,
|
||||||
@Default(DynamicSchemeVariant.tonalSpot) DynamicSchemeVariant schemeVariant,
|
@Default(DynamicSchemeVariant.tonalSpot) DynamicSchemeVariant schemeVariant,
|
||||||
@Default(false) bool pureBlack,
|
@Default(false) bool pureBlack,
|
||||||
|
@Default(TextScale()) TextScale textScale,
|
||||||
}) = _ThemeProps;
|
}) = _ThemeProps;
|
||||||
|
|
||||||
factory ThemeProps.fromJson(Map<String, Object?> json) =>
|
factory ThemeProps.fromJson(Map<String, Object?> json) =>
|
||||||
|
|||||||
@@ -1092,6 +1092,203 @@ abstract class _Connection implements Connection {
|
|||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log _$LogFromJson(Map<String, dynamic> json) {
|
||||||
|
return _Log.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$Log {
|
||||||
|
@JsonKey(name: "LogLevel")
|
||||||
|
LogLevel get logLevel => throw _privateConstructorUsedError;
|
||||||
|
@JsonKey(name: "Payload")
|
||||||
|
String get payload => throw _privateConstructorUsedError;
|
||||||
|
@JsonKey(fromJson: _logDateTime)
|
||||||
|
String get dateTime => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Serializes this Log to a JSON map.
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Create a copy of Log
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
$LogCopyWith<Log> get copyWith => throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $LogCopyWith<$Res> {
|
||||||
|
factory $LogCopyWith(Log value, $Res Function(Log) then) =
|
||||||
|
_$LogCopyWithImpl<$Res, Log>;
|
||||||
|
@useResult
|
||||||
|
$Res call(
|
||||||
|
{@JsonKey(name: "LogLevel") LogLevel logLevel,
|
||||||
|
@JsonKey(name: "Payload") String payload,
|
||||||
|
@JsonKey(fromJson: _logDateTime) String dateTime});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$LogCopyWithImpl<$Res, $Val extends Log> implements $LogCopyWith<$Res> {
|
||||||
|
_$LogCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
/// Create a copy of Log
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? logLevel = null,
|
||||||
|
Object? payload = null,
|
||||||
|
Object? dateTime = null,
|
||||||
|
}) {
|
||||||
|
return _then(_value.copyWith(
|
||||||
|
logLevel: null == logLevel
|
||||||
|
? _value.logLevel
|
||||||
|
: logLevel // ignore: cast_nullable_to_non_nullable
|
||||||
|
as LogLevel,
|
||||||
|
payload: null == payload
|
||||||
|
? _value.payload
|
||||||
|
: payload // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
dateTime: null == dateTime
|
||||||
|
? _value.dateTime
|
||||||
|
: dateTime // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
) as $Val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$LogImplCopyWith<$Res> implements $LogCopyWith<$Res> {
|
||||||
|
factory _$$LogImplCopyWith(_$LogImpl value, $Res Function(_$LogImpl) then) =
|
||||||
|
__$$LogImplCopyWithImpl<$Res>;
|
||||||
|
@override
|
||||||
|
@useResult
|
||||||
|
$Res call(
|
||||||
|
{@JsonKey(name: "LogLevel") LogLevel logLevel,
|
||||||
|
@JsonKey(name: "Payload") String payload,
|
||||||
|
@JsonKey(fromJson: _logDateTime) String dateTime});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$LogImplCopyWithImpl<$Res> extends _$LogCopyWithImpl<$Res, _$LogImpl>
|
||||||
|
implements _$$LogImplCopyWith<$Res> {
|
||||||
|
__$$LogImplCopyWithImpl(_$LogImpl _value, $Res Function(_$LogImpl) _then)
|
||||||
|
: super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of Log
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? logLevel = null,
|
||||||
|
Object? payload = null,
|
||||||
|
Object? dateTime = null,
|
||||||
|
}) {
|
||||||
|
return _then(_$LogImpl(
|
||||||
|
logLevel: null == logLevel
|
||||||
|
? _value.logLevel
|
||||||
|
: logLevel // ignore: cast_nullable_to_non_nullable
|
||||||
|
as LogLevel,
|
||||||
|
payload: null == payload
|
||||||
|
? _value.payload
|
||||||
|
: payload // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
dateTime: null == dateTime
|
||||||
|
? _value.dateTime
|
||||||
|
: dateTime // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
class _$LogImpl implements _Log {
|
||||||
|
const _$LogImpl(
|
||||||
|
{@JsonKey(name: "LogLevel") this.logLevel = LogLevel.app,
|
||||||
|
@JsonKey(name: "Payload") this.payload = "",
|
||||||
|
@JsonKey(fromJson: _logDateTime) required this.dateTime});
|
||||||
|
|
||||||
|
factory _$LogImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$$LogImplFromJson(json);
|
||||||
|
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "LogLevel")
|
||||||
|
final LogLevel logLevel;
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "Payload")
|
||||||
|
final String payload;
|
||||||
|
@override
|
||||||
|
@JsonKey(fromJson: _logDateTime)
|
||||||
|
final String dateTime;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'Log(logLevel: $logLevel, payload: $payload, dateTime: $dateTime)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$LogImpl &&
|
||||||
|
(identical(other.logLevel, logLevel) ||
|
||||||
|
other.logLevel == logLevel) &&
|
||||||
|
(identical(other.payload, payload) || other.payload == payload) &&
|
||||||
|
(identical(other.dateTime, dateTime) ||
|
||||||
|
other.dateTime == dateTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType, logLevel, payload, dateTime);
|
||||||
|
|
||||||
|
/// Create a copy of Log
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$LogImplCopyWith<_$LogImpl> get copyWith =>
|
||||||
|
__$$LogImplCopyWithImpl<_$LogImpl>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$$LogImplToJson(
|
||||||
|
this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _Log implements Log {
|
||||||
|
const factory _Log(
|
||||||
|
{@JsonKey(name: "LogLevel") final LogLevel logLevel,
|
||||||
|
@JsonKey(name: "Payload") final String payload,
|
||||||
|
@JsonKey(fromJson: _logDateTime) required final String dateTime}) =
|
||||||
|
_$LogImpl;
|
||||||
|
|
||||||
|
factory _Log.fromJson(Map<String, dynamic> json) = _$LogImpl.fromJson;
|
||||||
|
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "LogLevel")
|
||||||
|
LogLevel get logLevel;
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "Payload")
|
||||||
|
String get payload;
|
||||||
|
@override
|
||||||
|
@JsonKey(fromJson: _logDateTime)
|
||||||
|
String get dateTime;
|
||||||
|
|
||||||
|
/// Create a copy of Log
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
_$$LogImplCopyWith<_$LogImpl> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$LogsState {
|
mixin _$LogsState {
|
||||||
List<Log> get logs => throw _privateConstructorUsedError;
|
List<Log> get logs => throw _privateConstructorUsedError;
|
||||||
|
|||||||
@@ -6,25 +6,6 @@ part of '../common.dart';
|
|||||||
// JsonSerializableGenerator
|
// JsonSerializableGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
Log _$LogFromJson(Map<String, dynamic> json) => Log(
|
|
||||||
logLevel: $enumDecode(_$LogLevelEnumMap, json['LogLevel']),
|
|
||||||
payload: json['Payload'] as String?,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$LogToJson(Log instance) => <String, dynamic>{
|
|
||||||
'LogLevel': _$LogLevelEnumMap[instance.logLevel]!,
|
|
||||||
'Payload': instance.payload,
|
|
||||||
};
|
|
||||||
|
|
||||||
const _$LogLevelEnumMap = {
|
|
||||||
LogLevel.debug: 'debug',
|
|
||||||
LogLevel.info: 'info',
|
|
||||||
LogLevel.warning: 'warning',
|
|
||||||
LogLevel.error: 'error',
|
|
||||||
LogLevel.silent: 'silent',
|
|
||||||
LogLevel.app: 'app',
|
|
||||||
};
|
|
||||||
|
|
||||||
_$PackageImpl _$$PackageImplFromJson(Map<String, dynamic> json) =>
|
_$PackageImpl _$$PackageImplFromJson(Map<String, dynamic> json) =>
|
||||||
_$PackageImpl(
|
_$PackageImpl(
|
||||||
packageName: json['packageName'] as String,
|
packageName: json['packageName'] as String,
|
||||||
@@ -88,6 +69,28 @@ Map<String, dynamic> _$$ConnectionImplToJson(_$ConnectionImpl instance) =>
|
|||||||
'chains': instance.chains,
|
'chains': instance.chains,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_$LogImpl _$$LogImplFromJson(Map<String, dynamic> json) => _$LogImpl(
|
||||||
|
logLevel: $enumDecodeNullable(_$LogLevelEnumMap, json['LogLevel']) ??
|
||||||
|
LogLevel.app,
|
||||||
|
payload: json['Payload'] as String? ?? "",
|
||||||
|
dateTime: _logDateTime(json['dateTime']),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$LogImplToJson(_$LogImpl instance) => <String, dynamic>{
|
||||||
|
'LogLevel': _$LogLevelEnumMap[instance.logLevel]!,
|
||||||
|
'Payload': instance.payload,
|
||||||
|
'dateTime': instance.dateTime,
|
||||||
|
};
|
||||||
|
|
||||||
|
const _$LogLevelEnumMap = {
|
||||||
|
LogLevel.debug: 'debug',
|
||||||
|
LogLevel.info: 'info',
|
||||||
|
LogLevel.warning: 'warning',
|
||||||
|
LogLevel.error: 'error',
|
||||||
|
LogLevel.silent: 'silent',
|
||||||
|
LogLevel.app: 'app',
|
||||||
|
};
|
||||||
|
|
||||||
_$DAVImpl _$$DAVImplFromJson(Map<String, dynamic> json) => _$DAVImpl(
|
_$DAVImpl _$$DAVImplFromJson(Map<String, dynamic> json) => _$DAVImpl(
|
||||||
uri: json['uri'] as String,
|
uri: json['uri'] as String,
|
||||||
user: json['user'] as String,
|
user: json['user'] as String,
|
||||||
|
|||||||
@@ -1740,6 +1740,170 @@ abstract class _ProxiesStyle implements ProxiesStyle {
|
|||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextScale _$TextScaleFromJson(Map<String, dynamic> json) {
|
||||||
|
return _TextScale.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$TextScale {
|
||||||
|
dynamic get enable => throw _privateConstructorUsedError;
|
||||||
|
dynamic get scale => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Serializes this TextScale to a JSON map.
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Create a copy of TextScale
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
$TextScaleCopyWith<TextScale> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $TextScaleCopyWith<$Res> {
|
||||||
|
factory $TextScaleCopyWith(TextScale value, $Res Function(TextScale) then) =
|
||||||
|
_$TextScaleCopyWithImpl<$Res, TextScale>;
|
||||||
|
@useResult
|
||||||
|
$Res call({dynamic enable, dynamic scale});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$TextScaleCopyWithImpl<$Res, $Val extends TextScale>
|
||||||
|
implements $TextScaleCopyWith<$Res> {
|
||||||
|
_$TextScaleCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
/// Create a copy of TextScale
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? enable = freezed,
|
||||||
|
Object? scale = freezed,
|
||||||
|
}) {
|
||||||
|
return _then(_value.copyWith(
|
||||||
|
enable: freezed == enable
|
||||||
|
? _value.enable
|
||||||
|
: enable // ignore: cast_nullable_to_non_nullable
|
||||||
|
as dynamic,
|
||||||
|
scale: freezed == scale
|
||||||
|
? _value.scale
|
||||||
|
: scale // ignore: cast_nullable_to_non_nullable
|
||||||
|
as dynamic,
|
||||||
|
) as $Val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$TextScaleImplCopyWith<$Res>
|
||||||
|
implements $TextScaleCopyWith<$Res> {
|
||||||
|
factory _$$TextScaleImplCopyWith(
|
||||||
|
_$TextScaleImpl value, $Res Function(_$TextScaleImpl) then) =
|
||||||
|
__$$TextScaleImplCopyWithImpl<$Res>;
|
||||||
|
@override
|
||||||
|
@useResult
|
||||||
|
$Res call({dynamic enable, dynamic scale});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$TextScaleImplCopyWithImpl<$Res>
|
||||||
|
extends _$TextScaleCopyWithImpl<$Res, _$TextScaleImpl>
|
||||||
|
implements _$$TextScaleImplCopyWith<$Res> {
|
||||||
|
__$$TextScaleImplCopyWithImpl(
|
||||||
|
_$TextScaleImpl _value, $Res Function(_$TextScaleImpl) _then)
|
||||||
|
: super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of TextScale
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? enable = freezed,
|
||||||
|
Object? scale = freezed,
|
||||||
|
}) {
|
||||||
|
return _then(_$TextScaleImpl(
|
||||||
|
enable: freezed == enable ? _value.enable! : enable,
|
||||||
|
scale: freezed == scale ? _value.scale! : scale,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
class _$TextScaleImpl implements _TextScale {
|
||||||
|
const _$TextScaleImpl({this.enable = false, this.scale = 1.0});
|
||||||
|
|
||||||
|
factory _$TextScaleImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$$TextScaleImplFromJson(json);
|
||||||
|
|
||||||
|
@override
|
||||||
|
@JsonKey()
|
||||||
|
final dynamic enable;
|
||||||
|
@override
|
||||||
|
@JsonKey()
|
||||||
|
final dynamic scale;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'TextScale(enable: $enable, scale: $scale)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$TextScaleImpl &&
|
||||||
|
const DeepCollectionEquality().equals(other.enable, enable) &&
|
||||||
|
const DeepCollectionEquality().equals(other.scale, scale));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(
|
||||||
|
runtimeType,
|
||||||
|
const DeepCollectionEquality().hash(enable),
|
||||||
|
const DeepCollectionEquality().hash(scale));
|
||||||
|
|
||||||
|
/// Create a copy of TextScale
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$TextScaleImplCopyWith<_$TextScaleImpl> get copyWith =>
|
||||||
|
__$$TextScaleImplCopyWithImpl<_$TextScaleImpl>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$$TextScaleImplToJson(
|
||||||
|
this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _TextScale implements TextScale {
|
||||||
|
const factory _TextScale({final dynamic enable, final dynamic scale}) =
|
||||||
|
_$TextScaleImpl;
|
||||||
|
|
||||||
|
factory _TextScale.fromJson(Map<String, dynamic> json) =
|
||||||
|
_$TextScaleImpl.fromJson;
|
||||||
|
|
||||||
|
@override
|
||||||
|
dynamic get enable;
|
||||||
|
@override
|
||||||
|
dynamic get scale;
|
||||||
|
|
||||||
|
/// Create a copy of TextScale
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
_$$TextScaleImplCopyWith<_$TextScaleImpl> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
ThemeProps _$ThemePropsFromJson(Map<String, dynamic> json) {
|
ThemeProps _$ThemePropsFromJson(Map<String, dynamic> json) {
|
||||||
return _ThemeProps.fromJson(json);
|
return _ThemeProps.fromJson(json);
|
||||||
}
|
}
|
||||||
@@ -1751,6 +1915,7 @@ mixin _$ThemeProps {
|
|||||||
ThemeMode get themeMode => throw _privateConstructorUsedError;
|
ThemeMode get themeMode => throw _privateConstructorUsedError;
|
||||||
DynamicSchemeVariant get schemeVariant => throw _privateConstructorUsedError;
|
DynamicSchemeVariant get schemeVariant => throw _privateConstructorUsedError;
|
||||||
bool get pureBlack => throw _privateConstructorUsedError;
|
bool get pureBlack => throw _privateConstructorUsedError;
|
||||||
|
TextScale get textScale => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
/// Serializes this ThemeProps to a JSON map.
|
/// Serializes this ThemeProps to a JSON map.
|
||||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
@@ -1773,7 +1938,10 @@ abstract class $ThemePropsCopyWith<$Res> {
|
|||||||
List<int> primaryColors,
|
List<int> primaryColors,
|
||||||
ThemeMode themeMode,
|
ThemeMode themeMode,
|
||||||
DynamicSchemeVariant schemeVariant,
|
DynamicSchemeVariant schemeVariant,
|
||||||
bool pureBlack});
|
bool pureBlack,
|
||||||
|
TextScale textScale});
|
||||||
|
|
||||||
|
$TextScaleCopyWith<$Res> get textScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -1796,6 +1964,7 @@ class _$ThemePropsCopyWithImpl<$Res, $Val extends ThemeProps>
|
|||||||
Object? themeMode = null,
|
Object? themeMode = null,
|
||||||
Object? schemeVariant = null,
|
Object? schemeVariant = null,
|
||||||
Object? pureBlack = null,
|
Object? pureBlack = null,
|
||||||
|
Object? textScale = null,
|
||||||
}) {
|
}) {
|
||||||
return _then(_value.copyWith(
|
return _then(_value.copyWith(
|
||||||
primaryColor: freezed == primaryColor
|
primaryColor: freezed == primaryColor
|
||||||
@@ -1818,8 +1987,22 @@ class _$ThemePropsCopyWithImpl<$Res, $Val extends ThemeProps>
|
|||||||
? _value.pureBlack
|
? _value.pureBlack
|
||||||
: pureBlack // ignore: cast_nullable_to_non_nullable
|
: pureBlack // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,
|
as bool,
|
||||||
|
textScale: null == textScale
|
||||||
|
? _value.textScale
|
||||||
|
: textScale // ignore: cast_nullable_to_non_nullable
|
||||||
|
as TextScale,
|
||||||
) as $Val);
|
) as $Val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a copy of ThemeProps
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$TextScaleCopyWith<$Res> get textScale {
|
||||||
|
return $TextScaleCopyWith<$Res>(_value.textScale, (value) {
|
||||||
|
return _then(_value.copyWith(textScale: value) as $Val);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -1835,7 +2018,11 @@ abstract class _$$ThemePropsImplCopyWith<$Res>
|
|||||||
List<int> primaryColors,
|
List<int> primaryColors,
|
||||||
ThemeMode themeMode,
|
ThemeMode themeMode,
|
||||||
DynamicSchemeVariant schemeVariant,
|
DynamicSchemeVariant schemeVariant,
|
||||||
bool pureBlack});
|
bool pureBlack,
|
||||||
|
TextScale textScale});
|
||||||
|
|
||||||
|
@override
|
||||||
|
$TextScaleCopyWith<$Res> get textScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -1856,6 +2043,7 @@ class __$$ThemePropsImplCopyWithImpl<$Res>
|
|||||||
Object? themeMode = null,
|
Object? themeMode = null,
|
||||||
Object? schemeVariant = null,
|
Object? schemeVariant = null,
|
||||||
Object? pureBlack = null,
|
Object? pureBlack = null,
|
||||||
|
Object? textScale = null,
|
||||||
}) {
|
}) {
|
||||||
return _then(_$ThemePropsImpl(
|
return _then(_$ThemePropsImpl(
|
||||||
primaryColor: freezed == primaryColor
|
primaryColor: freezed == primaryColor
|
||||||
@@ -1878,6 +2066,10 @@ class __$$ThemePropsImplCopyWithImpl<$Res>
|
|||||||
? _value.pureBlack
|
? _value.pureBlack
|
||||||
: pureBlack // ignore: cast_nullable_to_non_nullable
|
: pureBlack // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,
|
as bool,
|
||||||
|
textScale: null == textScale
|
||||||
|
? _value.textScale
|
||||||
|
: textScale // ignore: cast_nullable_to_non_nullable
|
||||||
|
as TextScale,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1890,7 +2082,8 @@ class _$ThemePropsImpl implements _ThemeProps {
|
|||||||
final List<int> primaryColors = defaultPrimaryColors,
|
final List<int> primaryColors = defaultPrimaryColors,
|
||||||
this.themeMode = ThemeMode.dark,
|
this.themeMode = ThemeMode.dark,
|
||||||
this.schemeVariant = DynamicSchemeVariant.tonalSpot,
|
this.schemeVariant = DynamicSchemeVariant.tonalSpot,
|
||||||
this.pureBlack = false})
|
this.pureBlack = false,
|
||||||
|
this.textScale = const TextScale()})
|
||||||
: _primaryColors = primaryColors;
|
: _primaryColors = primaryColors;
|
||||||
|
|
||||||
factory _$ThemePropsImpl.fromJson(Map<String, dynamic> json) =>
|
factory _$ThemePropsImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
@@ -1916,10 +2109,13 @@ class _$ThemePropsImpl implements _ThemeProps {
|
|||||||
@override
|
@override
|
||||||
@JsonKey()
|
@JsonKey()
|
||||||
final bool pureBlack;
|
final bool pureBlack;
|
||||||
|
@override
|
||||||
|
@JsonKey()
|
||||||
|
final TextScale textScale;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'ThemeProps(primaryColor: $primaryColor, primaryColors: $primaryColors, themeMode: $themeMode, schemeVariant: $schemeVariant, pureBlack: $pureBlack)';
|
return 'ThemeProps(primaryColor: $primaryColor, primaryColors: $primaryColors, themeMode: $themeMode, schemeVariant: $schemeVariant, pureBlack: $pureBlack, textScale: $textScale)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -1936,7 +2132,9 @@ class _$ThemePropsImpl implements _ThemeProps {
|
|||||||
(identical(other.schemeVariant, schemeVariant) ||
|
(identical(other.schemeVariant, schemeVariant) ||
|
||||||
other.schemeVariant == schemeVariant) &&
|
other.schemeVariant == schemeVariant) &&
|
||||||
(identical(other.pureBlack, pureBlack) ||
|
(identical(other.pureBlack, pureBlack) ||
|
||||||
other.pureBlack == pureBlack));
|
other.pureBlack == pureBlack) &&
|
||||||
|
(identical(other.textScale, textScale) ||
|
||||||
|
other.textScale == textScale));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -1947,7 +2145,8 @@ class _$ThemePropsImpl implements _ThemeProps {
|
|||||||
const DeepCollectionEquality().hash(_primaryColors),
|
const DeepCollectionEquality().hash(_primaryColors),
|
||||||
themeMode,
|
themeMode,
|
||||||
schemeVariant,
|
schemeVariant,
|
||||||
pureBlack);
|
pureBlack,
|
||||||
|
textScale);
|
||||||
|
|
||||||
/// Create a copy of ThemeProps
|
/// Create a copy of ThemeProps
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@@ -1971,7 +2170,8 @@ abstract class _ThemeProps implements ThemeProps {
|
|||||||
final List<int> primaryColors,
|
final List<int> primaryColors,
|
||||||
final ThemeMode themeMode,
|
final ThemeMode themeMode,
|
||||||
final DynamicSchemeVariant schemeVariant,
|
final DynamicSchemeVariant schemeVariant,
|
||||||
final bool pureBlack}) = _$ThemePropsImpl;
|
final bool pureBlack,
|
||||||
|
final TextScale textScale}) = _$ThemePropsImpl;
|
||||||
|
|
||||||
factory _ThemeProps.fromJson(Map<String, dynamic> json) =
|
factory _ThemeProps.fromJson(Map<String, dynamic> json) =
|
||||||
_$ThemePropsImpl.fromJson;
|
_$ThemePropsImpl.fromJson;
|
||||||
@@ -1986,6 +2186,8 @@ abstract class _ThemeProps implements ThemeProps {
|
|||||||
DynamicSchemeVariant get schemeVariant;
|
DynamicSchemeVariant get schemeVariant;
|
||||||
@override
|
@override
|
||||||
bool get pureBlack;
|
bool get pureBlack;
|
||||||
|
@override
|
||||||
|
TextScale get textScale;
|
||||||
|
|
||||||
/// Create a copy of ThemeProps
|
/// Create a copy of ThemeProps
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
|||||||
@@ -222,6 +222,18 @@ const _$ProxyCardTypeEnumMap = {
|
|||||||
ProxyCardType.min: 'min',
|
ProxyCardType.min: 'min',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_$TextScaleImpl _$$TextScaleImplFromJson(Map<String, dynamic> json) =>
|
||||||
|
_$TextScaleImpl(
|
||||||
|
enable: json['enable'] ?? false,
|
||||||
|
scale: json['scale'] ?? 1.0,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$TextScaleImplToJson(_$TextScaleImpl instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'enable': instance.enable,
|
||||||
|
'scale': instance.scale,
|
||||||
|
};
|
||||||
|
|
||||||
_$ThemePropsImpl _$$ThemePropsImplFromJson(Map<String, dynamic> json) =>
|
_$ThemePropsImpl _$$ThemePropsImplFromJson(Map<String, dynamic> json) =>
|
||||||
_$ThemePropsImpl(
|
_$ThemePropsImpl(
|
||||||
primaryColor: (json['primaryColor'] as num?)?.toInt(),
|
primaryColor: (json['primaryColor'] as num?)?.toInt(),
|
||||||
@@ -235,6 +247,9 @@ _$ThemePropsImpl _$$ThemePropsImplFromJson(Map<String, dynamic> json) =>
|
|||||||
_$DynamicSchemeVariantEnumMap, json['schemeVariant']) ??
|
_$DynamicSchemeVariantEnumMap, json['schemeVariant']) ??
|
||||||
DynamicSchemeVariant.tonalSpot,
|
DynamicSchemeVariant.tonalSpot,
|
||||||
pureBlack: json['pureBlack'] as bool? ?? false,
|
pureBlack: json['pureBlack'] as bool? ?? false,
|
||||||
|
textScale: json['textScale'] == null
|
||||||
|
? const TextScale()
|
||||||
|
: TextScale.fromJson(json['textScale'] as Map<String, dynamic>),
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$$ThemePropsImplToJson(_$ThemePropsImpl instance) =>
|
Map<String, dynamic> _$$ThemePropsImplToJson(_$ThemePropsImpl instance) =>
|
||||||
@@ -244,6 +259,7 @@ Map<String, dynamic> _$$ThemePropsImplToJson(_$ThemePropsImpl instance) =>
|
|||||||
'themeMode': _$ThemeModeEnumMap[instance.themeMode]!,
|
'themeMode': _$ThemeModeEnumMap[instance.themeMode]!,
|
||||||
'schemeVariant': _$DynamicSchemeVariantEnumMap[instance.schemeVariant]!,
|
'schemeVariant': _$DynamicSchemeVariantEnumMap[instance.schemeVariant]!,
|
||||||
'pureBlack': instance.pureBlack,
|
'pureBlack': instance.pureBlack,
|
||||||
|
'textScale': instance.textScale,
|
||||||
};
|
};
|
||||||
|
|
||||||
const _$ThemeModeEnumMap = {
|
const _$ThemeModeEnumMap = {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ typedef UpdateTasks = List<FutureOr Function()>;
|
|||||||
class GlobalState {
|
class GlobalState {
|
||||||
static GlobalState? _instance;
|
static GlobalState? _instance;
|
||||||
Map<Key, double> cacheScrollPosition = {};
|
Map<Key, double> cacheScrollPosition = {};
|
||||||
|
Map<Key, FixedMap<String, double>> cacheHeightMap = {};
|
||||||
bool isService = false;
|
bool isService = false;
|
||||||
Timer? timer;
|
Timer? timer;
|
||||||
Timer? groupsUpdateTimer;
|
Timer? groupsUpdateTimer;
|
||||||
@@ -66,7 +67,8 @@ class GlobalState {
|
|||||||
_initDynamicColor() async {
|
_initDynamicColor() async {
|
||||||
try {
|
try {
|
||||||
corePalette = await DynamicColorPlugin.getCorePalette();
|
corePalette = await DynamicColorPlugin.getCorePalette();
|
||||||
accentColor = await DynamicColorPlugin.getAccentColor() ?? Color(defaultPrimaryColor);
|
accentColor = await DynamicColorPlugin.getAccentColor() ??
|
||||||
|
Color(defaultPrimaryColor);
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ class DonutChartPainter extends CustomPainter {
|
|||||||
@override
|
@override
|
||||||
void paint(Canvas canvas, Size size) {
|
void paint(Canvas canvas, Size size) {
|
||||||
final center = Offset(size.width / 2, size.height / 2);
|
final center = Offset(size.width / 2, size.height / 2);
|
||||||
const strokeWidth = 10.0;
|
final strokeWidth = 10.0.ap;
|
||||||
final radius = min(size.width / 2, size.height / 2) - strokeWidth / 2;
|
final radius = min(size.width / 2, size.height / 2) - strokeWidth / 2;
|
||||||
|
|
||||||
final gapAngle = 2 * asin(strokeWidth * 1 / (2 * radius)) * 1.2;
|
final gapAngle = 2 * asin(strokeWidth * 1 / (2 * radius)) * 1.2;
|
||||||
|
|||||||
@@ -62,6 +62,22 @@ class OpenDelegate extends Delegate {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class NextDelegate extends Delegate {
|
||||||
|
final Widget widget;
|
||||||
|
final String title;
|
||||||
|
final double? maxWidth;
|
||||||
|
final Widget? action;
|
||||||
|
final bool blur;
|
||||||
|
|
||||||
|
const NextDelegate({
|
||||||
|
required this.title,
|
||||||
|
required this.widget,
|
||||||
|
this.maxWidth,
|
||||||
|
this.action,
|
||||||
|
this.blur = true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
class OptionsDelegate<T> extends Delegate {
|
class OptionsDelegate<T> extends Delegate {
|
||||||
final List<T> options;
|
final List<T> options;
|
||||||
final String title;
|
final String title;
|
||||||
@@ -138,6 +154,21 @@ class ListItem<T> extends StatelessWidget {
|
|||||||
this.tileTitleAlignment = ListTileTitleAlignment.center,
|
this.tileTitleAlignment = ListTileTitleAlignment.center,
|
||||||
}) : onTap = null;
|
}) : onTap = null;
|
||||||
|
|
||||||
|
const ListItem.next({
|
||||||
|
super.key,
|
||||||
|
required this.title,
|
||||||
|
this.subtitle,
|
||||||
|
this.leading,
|
||||||
|
this.padding = const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
this.trailing,
|
||||||
|
required NextDelegate this.delegate,
|
||||||
|
this.horizontalTitleGap,
|
||||||
|
this.dense,
|
||||||
|
this.titleTextStyle,
|
||||||
|
this.subtitleTextStyle,
|
||||||
|
this.tileTitleAlignment = ListTileTitleAlignment.center,
|
||||||
|
}) : onTap = null;
|
||||||
|
|
||||||
const ListItem.options({
|
const ListItem.options({
|
||||||
super.key,
|
super.key,
|
||||||
required this.title,
|
required this.title,
|
||||||
@@ -285,6 +316,34 @@ class ListItem<T> extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (delegate is NextDelegate) {
|
||||||
|
final nextDelegate = delegate as NextDelegate;
|
||||||
|
final child = SafeArea(
|
||||||
|
child: nextDelegate.widget,
|
||||||
|
);
|
||||||
|
|
||||||
|
return _buildListTile(
|
||||||
|
onTap: () {
|
||||||
|
showExtend(
|
||||||
|
context,
|
||||||
|
props: ExtendProps(
|
||||||
|
blur: nextDelegate.blur,
|
||||||
|
maxWidth: nextDelegate.maxWidth,
|
||||||
|
),
|
||||||
|
builder: (_, type) {
|
||||||
|
return AdaptiveSheetScaffold(
|
||||||
|
actions: [
|
||||||
|
if (nextDelegate.action != null) nextDelegate.action!,
|
||||||
|
],
|
||||||
|
type: type,
|
||||||
|
body: child,
|
||||||
|
title: nextDelegate.title,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
if (delegate is OptionsDelegate) {
|
if (delegate is OptionsDelegate) {
|
||||||
final optionsDelegate = delegate as OptionsDelegate<T>;
|
final optionsDelegate = delegate as OptionsDelegate<T>;
|
||||||
return _buildListTile(
|
return _buildListTile(
|
||||||
@@ -353,14 +412,11 @@ class ListItem<T> extends StatelessWidget {
|
|||||||
radioDelegate.onChanged!(radioDelegate.value);
|
radioDelegate.onChanged!(radioDelegate.value);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
leading: SizedBox(
|
leading: Radio<T>(
|
||||||
width: 32,
|
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||||
height: 32,
|
value: radioDelegate.value,
|
||||||
child: Radio<T>(
|
groupValue: radioDelegate.groupValue,
|
||||||
value: radioDelegate.value,
|
onChanged: radioDelegate.onChanged,
|
||||||
groupValue: radioDelegate.groupValue,
|
|
||||||
onChanged: radioDelegate.onChanged,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
trailing: trailing,
|
trailing: trailing,
|
||||||
);
|
);
|
||||||
|
|||||||
33
lib/widgets/notification.dart
Normal file
33
lib/widgets/notification.dart
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import 'package:fl_clash/models/config.dart';
|
||||||
|
import 'package:fl_clash/providers/config.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
|
class TextScaleNotification extends StatelessWidget {
|
||||||
|
final Widget child;
|
||||||
|
final Function(TextScale textScale) onNotification;
|
||||||
|
|
||||||
|
const TextScaleNotification({
|
||||||
|
super.key,
|
||||||
|
required this.child,
|
||||||
|
required this.onNotification,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Consumer(
|
||||||
|
builder: (_, ref, __) {
|
||||||
|
ref.listen(
|
||||||
|
themeSettingProvider.select((state) => state.textScale),
|
||||||
|
(prev, next) {
|
||||||
|
if (prev != next) {
|
||||||
|
onNotification(next);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return child;
|
||||||
|
},
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -125,25 +125,25 @@ class CommonScaffoldState extends State<CommonScaffold> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ThemeData _appBarTheme(BuildContext context) {
|
Widget _buildSearchingAppBarTheme(Widget child) {
|
||||||
final ThemeData theme = Theme.of(context);
|
final ThemeData theme = Theme.of(context);
|
||||||
final ColorScheme colorScheme = theme.colorScheme;
|
final ColorScheme colorScheme = theme.colorScheme;
|
||||||
return theme.copyWith(
|
return Theme(
|
||||||
appBarTheme: AppBarTheme(
|
data: theme.copyWith(
|
||||||
systemOverlayStyle: colorScheme.brightness == Brightness.dark
|
appBarTheme: theme.appBarTheme.copyWith(
|
||||||
? SystemUiOverlayStyle.light
|
backgroundColor: colorScheme.brightness == Brightness.dark
|
||||||
: SystemUiOverlayStyle.dark,
|
? Colors.grey[900]
|
||||||
backgroundColor: colorScheme.brightness == Brightness.dark
|
: Colors.white,
|
||||||
? Colors.grey[900]
|
iconTheme: theme.primaryIconTheme.copyWith(color: Colors.grey),
|
||||||
: Colors.white,
|
titleTextStyle: theme.textTheme.titleLarge,
|
||||||
iconTheme: theme.primaryIconTheme.copyWith(color: Colors.grey),
|
toolbarTextStyle: theme.textTheme.bodyMedium,
|
||||||
titleTextStyle: theme.textTheme.titleLarge,
|
),
|
||||||
toolbarTextStyle: theme.textTheme.bodyMedium,
|
inputDecorationTheme: InputDecorationTheme(
|
||||||
),
|
hintStyle: theme.inputDecorationTheme.hintStyle,
|
||||||
inputDecorationTheme: InputDecorationTheme(
|
border: InputBorder.none,
|
||||||
hintStyle: theme.inputDecorationTheme.hintStyle,
|
),
|
||||||
border: InputBorder.none,
|
|
||||||
),
|
),
|
||||||
|
child: child,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,72 +318,66 @@ class CommonScaffoldState extends State<CommonScaffold> {
|
|||||||
child: appBar,
|
child: appBar,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return _isSearch
|
return _isSearch ? _buildSearchingAppBarTheme(appBar) : appBar;
|
||||||
? Theme(
|
|
||||||
data: _appBarTheme(context),
|
|
||||||
child: CommonPopScope(
|
|
||||||
onPop: () {
|
|
||||||
if (_isSearch) {
|
|
||||||
_handleExitSearching();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
child: appBar,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: appBar;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PreferredSizeWidget _buildAppBar() {
|
PreferredSizeWidget _buildAppBar() {
|
||||||
return PreferredSize(
|
return PreferredSize(
|
||||||
preferredSize: const Size.fromHeight(kToolbarHeight),
|
preferredSize: const Size.fromHeight(kToolbarHeight),
|
||||||
child: Stack(
|
child: Theme(
|
||||||
alignment: Alignment.bottomCenter,
|
data: Theme.of(context).copyWith(
|
||||||
children: [
|
appBarTheme: AppBarTheme(
|
||||||
ValueListenableBuilder<AppBarState>(
|
systemOverlayStyle: SystemUiOverlayStyle(
|
||||||
valueListenable: _appBarState,
|
statusBarColor: Colors.transparent,
|
||||||
builder: (_, state, __) {
|
statusBarIconBrightness:
|
||||||
return _buildAppBarWrap(
|
Theme.of(context).brightness == Brightness.dark
|
||||||
AppBar(
|
? Brightness.light
|
||||||
centerTitle: widget.centerTitle ?? false,
|
: Brightness.dark,
|
||||||
systemOverlayStyle: SystemUiOverlayStyle(
|
systemNavigationBarIconBrightness:
|
||||||
statusBarColor: Colors.transparent,
|
Theme.of(context).brightness == Brightness.dark
|
||||||
statusBarIconBrightness:
|
? Brightness.light
|
||||||
Theme.of(context).brightness == Brightness.dark
|
: Brightness.dark,
|
||||||
? Brightness.light
|
systemNavigationBarColor: widget.bottomNavigationBar != null
|
||||||
: Brightness.dark,
|
? context.colorScheme.surfaceContainer
|
||||||
systemNavigationBarIconBrightness:
|
: context.colorScheme.surface,
|
||||||
Theme.of(context).brightness == Brightness.dark
|
systemNavigationBarDividerColor: Colors.transparent,
|
||||||
? Brightness.light
|
),
|
||||||
: Brightness.dark,
|
),
|
||||||
systemNavigationBarColor: widget.bottomNavigationBar != null
|
),
|
||||||
? context.colorScheme.surfaceContainer
|
child: widget.appBar ??
|
||||||
: context.colorScheme.surface,
|
Stack(
|
||||||
systemNavigationBarDividerColor: Colors.transparent,
|
alignment: Alignment.bottomCenter,
|
||||||
),
|
children: [
|
||||||
automaticallyImplyLeading: widget.automaticallyImplyLeading,
|
ValueListenableBuilder<AppBarState>(
|
||||||
leading: _buildLeading(),
|
valueListenable: _appBarState,
|
||||||
title: _buildTitle(state.searchState),
|
builder: (_, state, __) {
|
||||||
actions: _buildActions(
|
return _buildAppBarWrap(
|
||||||
state.searchState != null,
|
AppBar(
|
||||||
state.actions.isNotEmpty
|
centerTitle: widget.centerTitle ?? false,
|
||||||
? state.actions
|
automaticallyImplyLeading:
|
||||||
: widget.actions ?? [],
|
widget.automaticallyImplyLeading,
|
||||||
),
|
leading: _buildLeading(),
|
||||||
|
title: _buildTitle(state.searchState),
|
||||||
|
actions: _buildActions(
|
||||||
|
state.searchState != null,
|
||||||
|
state.actions.isNotEmpty
|
||||||
|
? state.actions
|
||||||
|
: widget.actions ?? [],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
ValueListenableBuilder(
|
||||||
},
|
valueListenable: _loading,
|
||||||
),
|
builder: (_, value, __) {
|
||||||
ValueListenableBuilder(
|
return value == true
|
||||||
valueListenable: _loading,
|
? const LinearProgressIndicator()
|
||||||
builder: (_, value, __) {
|
: Container();
|
||||||
return value == true
|
},
|
||||||
? const LinearProgressIndicator()
|
),
|
||||||
: Container();
|
],
|
||||||
},
|
),
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -391,49 +385,51 @@ class CommonScaffoldState extends State<CommonScaffold> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
assert(widget.appBar != null || widget.title != null);
|
assert(widget.appBar != null || widget.title != null);
|
||||||
final body = Column(
|
final body = SafeArea(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
child: Column(
|
||||||
children: [
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
ValueListenableBuilder(
|
children: [
|
||||||
valueListenable: _keywordsNotifier,
|
ValueListenableBuilder(
|
||||||
builder: (_, keywords, __) {
|
valueListenable: _keywordsNotifier,
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
builder: (_, keywords, __) {
|
||||||
if (_onKeywordsUpdate != null) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
_onKeywordsUpdate!(keywords);
|
if (_onKeywordsUpdate != null) {
|
||||||
|
_onKeywordsUpdate!(keywords);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (keywords.isEmpty) {
|
||||||
|
return SizedBox();
|
||||||
}
|
}
|
||||||
});
|
return Padding(
|
||||||
if (keywords.isEmpty) {
|
padding: const EdgeInsets.symmetric(
|
||||||
return SizedBox();
|
horizontal: 16,
|
||||||
}
|
vertical: 16,
|
||||||
return Padding(
|
),
|
||||||
padding: const EdgeInsets.symmetric(
|
child: Wrap(
|
||||||
horizontal: 16,
|
runSpacing: 8,
|
||||||
vertical: 16,
|
spacing: 8,
|
||||||
),
|
children: [
|
||||||
child: Wrap(
|
for (final keyword in keywords)
|
||||||
runSpacing: 8,
|
CommonChip(
|
||||||
spacing: 8,
|
label: keyword,
|
||||||
children: [
|
type: ChipType.delete,
|
||||||
for (final keyword in keywords)
|
onPressed: () {
|
||||||
CommonChip(
|
_deleteKeyword(keyword);
|
||||||
label: keyword,
|
},
|
||||||
type: ChipType.delete,
|
),
|
||||||
onPressed: () {
|
],
|
||||||
_deleteKeyword(keyword);
|
),
|
||||||
},
|
);
|
||||||
),
|
},
|
||||||
],
|
),
|
||||||
),
|
Expanded(
|
||||||
);
|
child: widget.body,
|
||||||
},
|
),
|
||||||
),
|
],
|
||||||
Expanded(
|
),
|
||||||
child: widget.body,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
final scaffold = Scaffold(
|
final scaffold = Scaffold(
|
||||||
appBar: widget.appBar ?? _buildAppBar(),
|
appBar: _buildAppBar(),
|
||||||
body: body,
|
body: body,
|
||||||
backgroundColor: widget.backgroundColor,
|
backgroundColor: widget.backgroundColor,
|
||||||
floatingActionButton: ValueListenableBuilder<Widget?>(
|
floatingActionButton: ValueListenableBuilder<Widget?>(
|
||||||
|
|||||||
@@ -1058,18 +1058,18 @@ class _RenderSegmentedControl<T extends Object> extends RenderBox
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _paintThumb(PaintingContext context, Offset offset, Rect thumbRect) {
|
void _paintThumb(PaintingContext context, Offset offset, Rect thumbRect) {
|
||||||
const List<BoxShadow> thumbShadow = <BoxShadow>[
|
// const List<BoxShadow> thumbShadow = <BoxShadow>[
|
||||||
BoxShadow(color: Color(0x1F000000), offset: Offset(0, 3), blurRadius: 8),
|
// BoxShadow(color: Color(0x1F000000), offset: Offset(0, 3), blurRadius: 8),
|
||||||
BoxShadow(color: Color(0x0A000000), offset: Offset(0, 3), blurRadius: 1),
|
// BoxShadow(color: Color(0x0A000000), offset: Offset(0, 3), blurRadius: 1),
|
||||||
];
|
// ];
|
||||||
|
|
||||||
final RRect thumbRRect =
|
final RRect thumbRRect =
|
||||||
RRect.fromRectAndRadius(thumbRect.shift(offset), _kThumbRadius);
|
RRect.fromRectAndRadius(thumbRect.shift(offset), _kThumbRadius);
|
||||||
|
|
||||||
for (final BoxShadow shadow in thumbShadow) {
|
// for (final BoxShadow shadow in thumbShadow) {
|
||||||
context.canvas
|
// context.canvas
|
||||||
.drawRRect(thumbRRect.shift(shadow.offset), shadow.toPaint());
|
// .drawRRect(thumbRRect.shift(shadow.offset), shadow.toPaint());
|
||||||
}
|
// }
|
||||||
|
|
||||||
context.canvas.drawRRect(
|
context.canvas.drawRRect(
|
||||||
thumbRRect.inflate(0.5), Paint()..color = const Color(0x0A000000));
|
thumbRRect.inflate(0.5), Paint()..color = const Color(0x0A000000));
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ class EmojiText extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return RichText(
|
return RichText(
|
||||||
|
textScaler: MediaQuery.of(context).textScaler,
|
||||||
maxLines: maxLines,
|
maxLines: maxLines,
|
||||||
overflow: overflow ?? TextOverflow.clip,
|
overflow: overflow ?? TextOverflow.clip,
|
||||||
text: TextSpan(
|
text: TextSpan(
|
||||||
|
|||||||
@@ -32,3 +32,4 @@ export 'effect.dart';
|
|||||||
export 'palette.dart';
|
export 'palette.dart';
|
||||||
export 'tab.dart';
|
export 'tab.dart';
|
||||||
export 'container.dart';
|
export 'container.dart';
|
||||||
|
export 'notification.dart';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
name: fl_clash
|
name: fl_clash
|
||||||
description: A multi-platform proxy client based on ClashMeta, simple and easy to use, open-source and ad-free.
|
description: A multi-platform proxy client based on ClashMeta, simple and easy to use, open-source and ad-free.
|
||||||
publish_to: 'none'
|
publish_to: 'none'
|
||||||
version: 0.8.83+202504221
|
version: 0.8.83+202504231
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=3.1.0 <4.0.0'
|
sdk: '>=3.1.0 <4.0.0'
|
||||||
|
|
||||||
@@ -93,5 +93,5 @@ ffigen:
|
|||||||
flutter_intl:
|
flutter_intl:
|
||||||
enabled: true
|
enabled: true
|
||||||
class_name: AppLocalizations
|
class_name: AppLocalizations
|
||||||
arb_dir: lib/l10n/arb
|
arb_dir: arb
|
||||||
output_dir: lib/l10n
|
output_dir: lib/l10n
|
||||||
@@ -4,6 +4,7 @@ import requests
|
|||||||
|
|
||||||
TELEGRAM_BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
|
TELEGRAM_BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
|
||||||
TAG = os.getenv("TAG")
|
TAG = os.getenv("TAG")
|
||||||
|
RUN_ID = os.getenv("RUN_ID")
|
||||||
|
|
||||||
IS_STABLE = "-" not in TAG
|
IS_STABLE = "-" not in TAG
|
||||||
|
|
||||||
@@ -45,7 +46,8 @@ if TAG:
|
|||||||
|
|
||||||
if IS_STABLE:
|
if IS_STABLE:
|
||||||
text += f"\nhttps://github.com/chen08209/FlClash/releases/tag/{TAG}\n"
|
text += f"\nhttps://github.com/chen08209/FlClash/releases/tag/{TAG}\n"
|
||||||
|
else:
|
||||||
|
text += f"\nhttps://github.com/chen08209/FlClash/actions/runs/{RUN_ID}\n"
|
||||||
|
|
||||||
if os.path.exists(release):
|
if os.path.exists(release):
|
||||||
text += "\n"
|
text += "\n"
|
||||||
|
|||||||
83
windows/packaging/exe/inno_setup.iss
Normal file
83
windows/packaging/exe/inno_setup.iss
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
[Setup]
|
||||||
|
AppId={{APP_ID}}
|
||||||
|
AppVersion={{APP_VERSION}}
|
||||||
|
AppName={{DISPLAY_NAME}}
|
||||||
|
AppPublisher={{PUBLISHER_NAME}}
|
||||||
|
AppPublisherURL={{PUBLISHER_URL}}
|
||||||
|
AppSupportURL={{PUBLISHER_URL}}
|
||||||
|
AppUpdatesURL={{PUBLISHER_URL}}
|
||||||
|
DefaultDirName={{INSTALL_DIR_NAME}}
|
||||||
|
DisableProgramGroupPage=yes
|
||||||
|
OutputDir=.
|
||||||
|
OutputBaseFilename={{OUTPUT_BASE_FILENAME}}
|
||||||
|
Compression=lzma
|
||||||
|
SolidCompression=yes
|
||||||
|
SetupIconFile={{SETUP_ICON_FILE}}
|
||||||
|
WizardStyle=modern
|
||||||
|
PrivilegesRequired={{PRIVILEGES_REQUIRED}}
|
||||||
|
ArchitecturesAllowed={{ARCH}}
|
||||||
|
ArchitecturesInstallIn64BitMode={{ARCH}}
|
||||||
|
|
||||||
|
[Code]
|
||||||
|
procedure KillProcesses;
|
||||||
|
var
|
||||||
|
Processes: TArrayOfString;
|
||||||
|
i: Integer;
|
||||||
|
ResultCode: Integer;
|
||||||
|
begin
|
||||||
|
Processes := ['FlClash.exe', 'FlClashCore.exe', 'FlClashHelperService.exe'];
|
||||||
|
|
||||||
|
for i := 0 to GetArrayLength(Processes)-1 do
|
||||||
|
begin
|
||||||
|
Exec('taskkill', '/f /im ' + Processes[i], '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function InitializeSetup(): Boolean;
|
||||||
|
begin
|
||||||
|
KillProcesses;
|
||||||
|
Result := True;
|
||||||
|
end;
|
||||||
|
|
||||||
|
[Languages]
|
||||||
|
{% for locale in LOCALES %}
|
||||||
|
{% if locale.lang == 'en' %}Name: "english"; MessagesFile: "compiler:Default.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'hy' %}Name: "armenian"; MessagesFile: "compiler:Languages\\Armenian.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'bg' %}Name: "bulgarian"; MessagesFile: "compiler:Languages\\Bulgarian.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'ca' %}Name: "catalan"; MessagesFile: "compiler:Languages\\Catalan.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'zh' %}
|
||||||
|
Name: "chineseSimplified"; MessagesFile: {% if locale.file %}{{ locale.file }}{% else %}"compiler:Languages\\ChineseSimplified.isl"{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% if locale.lang == 'co' %}Name: "corsican"; MessagesFile: "compiler:Languages\\Corsican.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'cs' %}Name: "czech"; MessagesFile: "compiler:Languages\\Czech.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'da' %}Name: "danish"; MessagesFile: "compiler:Languages\\Danish.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'nl' %}Name: "dutch"; MessagesFile: "compiler:Languages\\Dutch.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'fi' %}Name: "finnish"; MessagesFile: "compiler:Languages\\Finnish.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'fr' %}Name: "french"; MessagesFile: "compiler:Languages\\French.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'de' %}Name: "german"; MessagesFile: "compiler:Languages\\German.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'he' %}Name: "hebrew"; MessagesFile: "compiler:Languages\\Hebrew.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'is' %}Name: "icelandic"; MessagesFile: "compiler:Languages\\Icelandic.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'it' %}Name: "italian"; MessagesFile: "compiler:Languages\\Italian.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'ja' %}Name: "japanese"; MessagesFile: "compiler:Languages\\Japanese.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'no' %}Name: "norwegian"; MessagesFile: "compiler:Languages\\Norwegian.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'pl' %}Name: "polish"; MessagesFile: "compiler:Languages\\Polish.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'pt' %}Name: "portuguese"; MessagesFile: "compiler:Languages\\Portuguese.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'ru' %}Name: "russian"; MessagesFile: "compiler:Languages\\Russian.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'sk' %}Name: "slovak"; MessagesFile: "compiler:Languages\\Slovak.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'sl' %}Name: "slovenian"; MessagesFile: "compiler:Languages\\Slovenian.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'es' %}Name: "spanish"; MessagesFile: "compiler:Languages\\Spanish.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'tr' %}Name: "turkish"; MessagesFile: "compiler:Languages\\Turkish.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'uk' %}Name: "ukrainian"; MessagesFile: "compiler:Languages\\Ukrainian.isl"{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
[Tasks]
|
||||||
|
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: {% if CREATE_DESKTOP_ICON != true %}unchecked{% else %}checkedonce{% endif %}
|
||||||
|
[Files]
|
||||||
|
Source: "{{SOURCE_DIR}}\\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||||
|
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
||||||
|
|
||||||
|
[Icons]
|
||||||
|
Name: "{autoprograms}\\{{DISPLAY_NAME}}"; Filename: "{app}\\{{EXECUTABLE_NAME}}"
|
||||||
|
Name: "{autodesktop}\\{{DISPLAY_NAME}}"; Filename: "{app}\\{{EXECUTABLE_NAME}}"; Tasks: desktopicon
|
||||||
|
[Run]
|
||||||
|
Filename: "{app}\\{{EXECUTABLE_NAME}}"; Description: "{cm:LaunchProgram,{{DISPLAY_NAME}}}"; Flags: {% if PRIVILEGES_REQUIRED == 'admin' %}runascurrentuser{% endif %} nowait postinstall skipifsilent
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
script_template: inno_setup.iss
|
||||||
app_id: 728B3532-C74B-4870-9068-BE70FE12A3E6
|
app_id: 728B3532-C74B-4870-9068-BE70FE12A3E6
|
||||||
app_name: FlClash
|
app_name: FlClash
|
||||||
publisher: chen08209
|
publisher: chen08209
|
||||||
@@ -9,4 +10,5 @@ setup_icon_file: ..\windows\runner\resources\app_icon.ico
|
|||||||
locales:
|
locales:
|
||||||
- lang: zh
|
- lang: zh
|
||||||
file: ..\windows\packaging\exe\ChineseSimplified.isl
|
file: ..\windows\packaging\exe\ChineseSimplified.isl
|
||||||
- lang: en
|
- lang: en
|
||||||
|
privileges_required: admin
|
||||||
Reference in New Issue
Block a user