mirror of
https://github.com/wgh136/pixes.git
synced 2025-09-28 05:17:24 +00:00
Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
86c6f13282 | ||
![]() |
b69d2a0950 | ||
![]() |
c897891b2a | ||
![]() |
3c73439588 | ||
![]() |
2d16502154 | ||
![]() |
294498d8a7 | ||
![]() |
20dfbf5125 | ||
![]() |
63aa4ee8b0 | ||
![]() |
c8d4b3db88 | ||
![]() |
b1e7adb1c5 | ||
![]() |
0143a67fa0 |
13
.github/workflows/linux.yml
vendored
13
.github/workflows/linux.yml
vendored
@@ -11,13 +11,24 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
channel: 'stable'
|
channel: 'stable'
|
||||||
architecture: x64
|
architecture: x64
|
||||||
|
flutter-version-file: pubspec.yaml
|
||||||
- run: |
|
- run: |
|
||||||
sudo apt-get update -y
|
sudo apt-get update -y
|
||||||
sudo apt-get install -y ninja-build libgtk-3-dev
|
sudo apt-get install -y ninja-build libgtk-3-dev
|
||||||
dart pub global activate flutter_to_debian
|
dart pub global activate flutter_to_debian
|
||||||
- run: python3 debian/build.py
|
- run: python3 debian/build.py
|
||||||
- uses: actions/upload-artifact@v3
|
- run: dart run flutter_to_arch
|
||||||
|
- run: |
|
||||||
|
sudo rm -rf build/linux/arch/app.tar.gz
|
||||||
|
sudo rm -rf build/linux/arch/pkg
|
||||||
|
sudo rm -rf build/linux/arch/src
|
||||||
|
sudo rm -rf build/linux/arch/PKGBUILD
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: deb_build
|
name: deb_build
|
||||||
path: build/linux/x64/release/debian
|
path: build/linux/x64/release/debian
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: arch_build
|
||||||
|
path: build/linux/arch/
|
||||||
|
|
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
@@ -11,6 +11,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
channel: 'stable'
|
channel: 'stable'
|
||||||
architecture: x64
|
architecture: x64
|
||||||
|
flutter-version-file: pubspec.yaml
|
||||||
- run: sudo xcode-select --switch /Applications/Xcode_14.3.1.app
|
- run: sudo xcode-select --switch /Applications/Xcode_14.3.1.app
|
||||||
- run: flutter pub get
|
- run: flutter pub get
|
||||||
- run: flutter build ios --release --no-codesign
|
- run: flutter build ios --release --no-codesign
|
||||||
@@ -27,6 +28,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
channel: 'stable'
|
channel: 'stable'
|
||||||
architecture: x64
|
architecture: x64
|
||||||
|
flutter-version-file: pubspec.yaml
|
||||||
- run: sudo xcode-select --switch /Applications/Xcode_14.3.1.app
|
- run: sudo xcode-select --switch /Applications/Xcode_14.3.1.app
|
||||||
- run: flutter pub get
|
- run: flutter pub get
|
||||||
- run: flutter build macos --release
|
- run: flutter build macos --release
|
||||||
|
@@ -1,10 +1,9 @@
|
|||||||
# pixes
|
# pixes
|
||||||
|
|
||||||
[](https://flutter.dev/)
|
[](https://flutter.dev/)
|
||||||
[](https://github.com/wgh136/pixes/blob/master/LICENSE)
|
[](https://github.com/wgh136/pixes/blob/master/LICENSE)
|
||||||
[](https://github.com/wgh136/pixes)
|
[](https://github.com/wgh136/pixes)
|
||||||
[](https://github.com/wgh136/pixes/stargazers)
|
[](https://github.com/wgh136/pixes/stargazers)
|
||||||
[](https://t.me/pica_group)
|
|
||||||
|
|
||||||
非官方 Pixiv app, 支持 Windows, Android, iOS, macOS, linux
|
非官方 Pixiv app, 支持 Windows, Android, iOS, macOS, linux
|
||||||
|
|
||||||
|
@@ -63,15 +63,18 @@ class _IllustWidgetState extends State<IllustWidget> {
|
|||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
Positioned.fill(
|
Positioned.fill(
|
||||||
child: Container(
|
|
||||||
width: width,
|
|
||||||
height: height,
|
|
||||||
padding:
|
|
||||||
const EdgeInsets.symmetric(horizontal: 8.0, vertical: 8.0),
|
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: EdgeInsets.zero,
|
width: width,
|
||||||
decoration: BoxDecoration(
|
height: height,
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 8.0, vertical: 8.0),
|
||||||
|
child: Container(
|
||||||
|
width: double.infinity,
|
||||||
|
height: double.infinity,
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(4.0),
|
borderRadius: BorderRadius.circular(4.0),
|
||||||
|
color: FluentTheme.of(context).cardColor,
|
||||||
border: () {
|
border: () {
|
||||||
var emphasis = widget.illust.author.isFollowed &&
|
var emphasis = widget.illust.author.isFollowed &&
|
||||||
appdata.settings[
|
appdata.settings[
|
||||||
@@ -83,28 +86,30 @@ class _IllustWidgetState extends State<IllustWidget> {
|
|||||||
.withOpacity(0.64);
|
.withOpacity(0.64);
|
||||||
var width = emphasis ? 1.6 : 1.0;
|
var width = emphasis ? 1.6 : 1.0;
|
||||||
return Border.all(color: color, width: width);
|
return Border.all(color: color, width: width);
|
||||||
}()),
|
}(),
|
||||||
margin: EdgeInsets.zero,
|
),
|
||||||
child: GestureDetector(
|
margin: EdgeInsets.zero,
|
||||||
onTap: widget.onTap ??
|
child: GestureDetector(
|
||||||
() {
|
onTap: widget.onTap ??
|
||||||
context.to(() => IllustPage(widget.illust));
|
() {
|
||||||
},
|
context.to(() => IllustPage(widget.illust));
|
||||||
onSecondaryTapUp: showMenu,
|
},
|
||||||
onLongPress: showMenu,
|
onSecondaryTapUp: showMenu,
|
||||||
child: ClipRRect(
|
onLongPress: showMenu,
|
||||||
borderRadius: BorderRadius.circular(4.0),
|
child: ClipRRect(
|
||||||
child: AnimatedImage(
|
borderRadius: BorderRadius.circular(4.0),
|
||||||
image: CachedImageProvider(
|
child: AnimatedImage(
|
||||||
widget.illust.images.first.medium),
|
image: CachedImageProvider(
|
||||||
fit: BoxFit.cover,
|
widget.illust.images.first.medium),
|
||||||
width: width - 16.0,
|
fit: BoxFit.cover,
|
||||||
height: height - 16.0,
|
width: width - 16.0,
|
||||||
|
height: height - 16.0,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)),
|
),
|
||||||
if (widget.illust.images.length > 1)
|
if (widget.illust.images.length > 1)
|
||||||
Positioned(
|
Positioned(
|
||||||
top: 12,
|
top: 12,
|
||||||
|
@@ -40,7 +40,7 @@ class KeyEventListenerState extends State<KeyEventListener> {
|
|||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
onKeyEvent: (node, event) {
|
onKeyEvent: (node, event) {
|
||||||
if (event is! KeyUpEvent) return KeyEventResult.handled;
|
if (event is! KeyUpEvent) return KeyEventResult.ignored;
|
||||||
if (event.logicalKey == LogicalKeyboardKey.escape) {
|
if (event.logicalKey == LogicalKeyboardKey.escape) {
|
||||||
if (App.rootNavigatorKey.currentState?.canPop() ?? false) {
|
if (App.rootNavigatorKey.currentState?.canPop() ?? false) {
|
||||||
App.rootNavigatorKey.currentState?.pop();
|
App.rootNavigatorKey.currentState?.pop();
|
||||||
@@ -52,7 +52,7 @@ class KeyEventListenerState extends State<KeyEventListener> {
|
|||||||
for (var handler in _handlers) {
|
for (var handler in _handlers) {
|
||||||
handler(event.logicalKey);
|
handler(event.logicalKey);
|
||||||
}
|
}
|
||||||
return KeyEventResult.handled;
|
return KeyEventResult.ignored;
|
||||||
},
|
},
|
||||||
child: widget.child,
|
child: widget.child,
|
||||||
);
|
);
|
||||||
|
@@ -12,7 +12,7 @@ export "state_controller.dart";
|
|||||||
export "navigation.dart";
|
export "navigation.dart";
|
||||||
|
|
||||||
class _App {
|
class _App {
|
||||||
final version = "1.0.8";
|
final version = "1.0.9";
|
||||||
|
|
||||||
bool get isAndroid => Platform.isAndroid;
|
bool get isAndroid => Platform.isAndroid;
|
||||||
bool get isIOS => Platform.isIOS;
|
bool get isIOS => Platform.isIOS;
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
@@ -109,12 +110,53 @@ class AppDio extends DioForNative {
|
|||||||
CancelToken? cancelToken,
|
CancelToken? cancelToken,
|
||||||
Options? options,
|
Options? options,
|
||||||
ProgressCallback? onSendProgress,
|
ProgressCallback? onSendProgress,
|
||||||
ProgressCallback? onReceiveProgress}) {
|
ProgressCallback? onReceiveProgress}) async{
|
||||||
if (!isInitialized) {
|
if (!isInitialized) {
|
||||||
isInitialized = true;
|
isInitialized = true;
|
||||||
interceptors.add(MyLogInterceptor());
|
interceptors.add(MyLogInterceptor());
|
||||||
}
|
}
|
||||||
return super.request(path,
|
if(T == Map<String, dynamic>) {
|
||||||
|
var res = await super.request<String>(path,
|
||||||
|
data: data,
|
||||||
|
queryParameters: queryParameters,
|
||||||
|
cancelToken: cancelToken,
|
||||||
|
options: options,
|
||||||
|
onSendProgress: onSendProgress,
|
||||||
|
onReceiveProgress: onReceiveProgress);
|
||||||
|
if(res.data == null) {
|
||||||
|
return Response(
|
||||||
|
data: null,
|
||||||
|
requestOptions: res.requestOptions,
|
||||||
|
statusCode: res.statusCode,
|
||||||
|
statusMessage: res.statusMessage,
|
||||||
|
isRedirect: res.isRedirect,
|
||||||
|
redirects: res.redirects,
|
||||||
|
extra: res.extra,
|
||||||
|
headers: res.headers
|
||||||
|
);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
var json = jsonDecode(res.data!);
|
||||||
|
return Response(
|
||||||
|
data: json,
|
||||||
|
requestOptions: res.requestOptions,
|
||||||
|
statusCode: res.statusCode,
|
||||||
|
statusMessage: res.statusMessage,
|
||||||
|
isRedirect: res.isRedirect,
|
||||||
|
redirects: res.redirects,
|
||||||
|
extra: res.extra,
|
||||||
|
headers: res.headers
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch(e) {
|
||||||
|
var data = res.data!;
|
||||||
|
if(data.length > 50) {
|
||||||
|
data = "${data.substring(0, 50)}...";
|
||||||
|
}
|
||||||
|
throw "Failed to decode response: $e\n$data";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.request<T>(path,
|
||||||
data: data,
|
data: data,
|
||||||
queryParameters: queryParameters,
|
queryParameters: queryParameters,
|
||||||
cancelToken: cancelToken,
|
cancelToken: cancelToken,
|
||||||
|
@@ -324,7 +324,7 @@ class DownloadManager {
|
|||||||
where illust_id = ?;
|
where illust_id = ?;
|
||||||
''', [illust.illustId]);
|
''', [illust.illustId]);
|
||||||
for(var image in images) {
|
for(var image in images) {
|
||||||
File(image["path"] as String).deleteIfExists();
|
File(image["path"] as String).deleteIgnoreError();
|
||||||
}
|
}
|
||||||
_db.execute('''
|
_db.execute('''
|
||||||
delete from images
|
delete from images
|
||||||
|
75
lib/network/translator.dart
Normal file
75
lib/network/translator.dart
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
import 'package:pixes/network/app_dio.dart';
|
||||||
|
|
||||||
|
abstract class Translator {
|
||||||
|
static Translator? _instance;
|
||||||
|
|
||||||
|
static Translator get instance {
|
||||||
|
if (_instance == null) {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
return _instance!;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init() {
|
||||||
|
_instance = GoogleTranslator();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Translates the given [text] to the given [to] language.
|
||||||
|
Future<String> translate(String text, String to);
|
||||||
|
}
|
||||||
|
|
||||||
|
class GoogleTranslator implements Translator {
|
||||||
|
final Dio _dio = AppDio();
|
||||||
|
|
||||||
|
String get url => 'https://translate.google.com/translate_a/single';
|
||||||
|
|
||||||
|
Map<String, dynamic> buildBody(String text, String to) {
|
||||||
|
return {
|
||||||
|
'q': text,
|
||||||
|
'client': 'at',
|
||||||
|
'sl': 'auto',
|
||||||
|
'tl': to,
|
||||||
|
'dt': 't',
|
||||||
|
'ie': 'UTF-8',
|
||||||
|
'oe': 'UTF-8',
|
||||||
|
'dj': '1',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String> translatePart(String part, String to) async {
|
||||||
|
final response = await _dio.post(
|
||||||
|
url,
|
||||||
|
data: buildBody(part, to),
|
||||||
|
options: Options(
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
var buffer = StringBuffer();
|
||||||
|
for(var e in response.data['sentences']) {
|
||||||
|
buffer.write(e['trans']);
|
||||||
|
}
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<String> translate(String text, String to) async {
|
||||||
|
final lines = text.split('\n');
|
||||||
|
var buffer = StringBuffer();
|
||||||
|
var result = '';
|
||||||
|
for(int i=0; i<lines.length; i++) {
|
||||||
|
final line = lines[i];
|
||||||
|
if (buffer.length + line.length > 5000) {
|
||||||
|
result += await translatePart(buffer.toString(), to);
|
||||||
|
buffer.clear();
|
||||||
|
}
|
||||||
|
buffer.write(line);
|
||||||
|
buffer.write('\n');
|
||||||
|
}
|
||||||
|
if (buffer.isNotEmpty) {
|
||||||
|
result += await translatePart(buffer.toString(), to);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@@ -311,7 +311,26 @@ class _MainPageState extends State<MainPage>
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
).paddingTop(4).paddingLeft(4),
|
).paddingTop(4).paddingLeft(4),
|
||||||
if (App.isDesktop) const SizedBox(width: 128),
|
if (App.isDesktop)
|
||||||
|
const SizedBox(width: 128)
|
||||||
|
else
|
||||||
|
Tooltip(
|
||||||
|
message: "Search".tl,
|
||||||
|
child: IconButton(
|
||||||
|
icon: const Icon(
|
||||||
|
MdIcons.search,
|
||||||
|
size: 18,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
if(index == 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
index = 1;
|
||||||
|
});
|
||||||
|
navigate(1);
|
||||||
|
},
|
||||||
|
)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -339,7 +358,6 @@ class _MainPageState extends State<MainPage>
|
|||||||
PopInvokedCallback? get onPopInvoked => onPop;
|
PopInvokedCallback? get onPopInvoked => onPop;
|
||||||
|
|
||||||
void onPop(bool value) {
|
void onPop(bool value) {
|
||||||
print("ok");
|
|
||||||
if (App.rootNavigatorKey.currentState?.canPop() ?? false) {
|
if (App.rootNavigatorKey.currentState?.canPop() ?? false) {
|
||||||
App.rootNavigatorKey.currentState?.pop();
|
App.rootNavigatorKey.currentState?.pop();
|
||||||
} else if (App.mainNavigatorKey?.currentState?.canPop() ?? false) {
|
} else if (App.mainNavigatorKey?.currentState?.canPop() ?? false) {
|
||||||
|
@@ -646,7 +646,7 @@ class _NovelPageWithIdState extends LoadingState<NovelPageWithId, Novel> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _RelatedNovelsPage extends StatefulWidget {
|
class _RelatedNovelsPage extends StatefulWidget {
|
||||||
const _RelatedNovelsPage(this.id, {super.key});
|
const _RelatedNovelsPage(this.id);
|
||||||
|
|
||||||
final String id;
|
final String id;
|
||||||
|
|
||||||
|
@@ -7,7 +7,9 @@ import 'package:pixes/components/page_route.dart';
|
|||||||
import 'package:pixes/components/title_bar.dart';
|
import 'package:pixes/components/title_bar.dart';
|
||||||
import 'package:pixes/foundation/app.dart';
|
import 'package:pixes/foundation/app.dart';
|
||||||
import 'package:pixes/foundation/image_provider.dart';
|
import 'package:pixes/foundation/image_provider.dart';
|
||||||
|
import 'package:pixes/foundation/log.dart';
|
||||||
import 'package:pixes/network/network.dart';
|
import 'package:pixes/network/network.dart';
|
||||||
|
import 'package:pixes/network/translator.dart';
|
||||||
import 'package:pixes/pages/image_page.dart';
|
import 'package:pixes/pages/image_page.dart';
|
||||||
import 'package:pixes/pages/main_page.dart';
|
import 'package:pixes/pages/main_page.dart';
|
||||||
import 'package:pixes/utils/ext.dart';
|
import 'package:pixes/utils/ext.dart';
|
||||||
@@ -27,15 +29,36 @@ class _NovelReadingPageState extends LoadingState<NovelReadingPage, String> {
|
|||||||
|
|
||||||
bool isShowingSettings = false;
|
bool isShowingSettings = false;
|
||||||
|
|
||||||
|
String? translatedContent;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
action = TitleBarAction(MdIcons.tune, "Settings".tl, () {
|
action = TitleBarAction(MdIcons.tune, "Settings".tl, () {
|
||||||
if (!isShowingSettings) {
|
if (!isShowingSettings) {
|
||||||
_NovelReadingSettings.show(context, () {
|
_NovelReadingSettings.show(
|
||||||
setState(() {});
|
context,
|
||||||
}).then((value) {
|
() {
|
||||||
isShowingSettings = false;
|
setState(() {});
|
||||||
});
|
},
|
||||||
|
TranslationController(
|
||||||
|
content: data!,
|
||||||
|
isTranslated: translatedContent != null,
|
||||||
|
onTranslated: (s) {
|
||||||
|
setState(() {
|
||||||
|
translatedContent = s;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
revert: () {
|
||||||
|
setState(() {
|
||||||
|
translatedContent = null;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
).then(
|
||||||
|
(value) {
|
||||||
|
isShowingSettings = false;
|
||||||
|
},
|
||||||
|
);
|
||||||
isShowingSettings = true;
|
isShowingSettings = true;
|
||||||
} else {
|
} else {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
@@ -92,7 +115,7 @@ class _NovelReadingPageState extends LoadingState<NovelReadingPage, String> {
|
|||||||
);
|
);
|
||||||
yield const SizedBox(height: 12.0);
|
yield const SizedBox(height: 12.0);
|
||||||
|
|
||||||
var novelContent = data!.split('\n');
|
var novelContent = (translatedContent ?? data!).split('\n');
|
||||||
for (var content in novelContent) {
|
for (var content in novelContent) {
|
||||||
if (content.isEmpty) continue;
|
if (content.isEmpty) continue;
|
||||||
if (content.startsWith('[uploadedimage:')) {
|
if (content.startsWith('[uploadedimage:')) {
|
||||||
@@ -132,14 +155,38 @@ class _NovelReadingPageState extends LoadingState<NovelReadingPage, String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TranslationController {
|
||||||
|
final String content;
|
||||||
|
|
||||||
|
final bool isTranslated;
|
||||||
|
|
||||||
|
final void Function(String translated) onTranslated;
|
||||||
|
|
||||||
|
final void Function() revert;
|
||||||
|
|
||||||
|
const TranslationController({
|
||||||
|
required this.content,
|
||||||
|
required this.isTranslated,
|
||||||
|
required this.onTranslated,
|
||||||
|
required this.revert,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
class _NovelReadingSettings extends StatefulWidget {
|
class _NovelReadingSettings extends StatefulWidget {
|
||||||
const _NovelReadingSettings(this.callback);
|
const _NovelReadingSettings(this.callback, this.controller);
|
||||||
|
|
||||||
final void Function() callback;
|
final void Function() callback;
|
||||||
|
|
||||||
static Future show(BuildContext context, void Function() callback) {
|
final TranslationController controller;
|
||||||
return Navigator.of(context)
|
|
||||||
.push(SideBarRoute(_NovelReadingSettings(callback)));
|
static Future show(
|
||||||
|
BuildContext context,
|
||||||
|
void Function() callback,
|
||||||
|
TranslationController controller,
|
||||||
|
) {
|
||||||
|
return Navigator.of(context).push(
|
||||||
|
SideBarRoute(_NovelReadingSettings(callback, controller)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -256,9 +303,64 @@ class __NovelReadingSettingsState extends State<_NovelReadingSettings> {
|
|||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
),
|
).paddingBottom(8),
|
||||||
|
Card(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
child: ListTile(
|
||||||
|
title: Text("Translate Novel".tl),
|
||||||
|
trailing: widget.controller.isTranslated
|
||||||
|
? Button(
|
||||||
|
onPressed: () {
|
||||||
|
widget.controller.revert();
|
||||||
|
context.pop();
|
||||||
|
},
|
||||||
|
child: Text("Revert".tl),
|
||||||
|
)
|
||||||
|
: Button(
|
||||||
|
onPressed: translate,
|
||||||
|
child: isTranslating
|
||||||
|
? const SizedBox(
|
||||||
|
width: 42,
|
||||||
|
height: 18,
|
||||||
|
child: Center(
|
||||||
|
child: SizedBox.square(
|
||||||
|
dimension: 18,
|
||||||
|
child: ProgressRing(
|
||||||
|
strokeWidth: 2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Text("Translate".tl),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
).paddingHorizontal(8).paddingBottom(8),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isTranslating = false;
|
||||||
|
|
||||||
|
void translate() async {
|
||||||
|
setState(() {
|
||||||
|
isTranslating = true;
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
var translated = await Translator.instance
|
||||||
|
.translate(widget.controller.content, "zh-CN");
|
||||||
|
widget.controller.onTranslated(translated);
|
||||||
|
if (mounted) {
|
||||||
|
context.pop();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
setState(() {
|
||||||
|
isTranslating = false;
|
||||||
|
});
|
||||||
|
if (mounted) {
|
||||||
|
context.showToast(message: "Failed to translate".tl);
|
||||||
|
}
|
||||||
|
Log.error("Translate", e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -33,8 +33,6 @@ class _SearchPageState extends State<SearchPage> {
|
|||||||
|
|
||||||
int searchType = 0;
|
int searchType = 0;
|
||||||
|
|
||||||
final focusNode = FocusNode();
|
|
||||||
|
|
||||||
static const searchTypes = [
|
static const searchTypes = [
|
||||||
"Search artwork",
|
"Search artwork",
|
||||||
"Search novel",
|
"Search novel",
|
||||||
@@ -102,8 +100,6 @@ class _SearchPageState extends State<SearchPage> {
|
|||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TextBox(
|
child: TextBox(
|
||||||
focusNode: focusNode,
|
|
||||||
autofocus: false,
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||||
placeholder:
|
placeholder:
|
||||||
'${searchTypes[searchType].tl} / ${"Open link".tl}',
|
'${searchTypes[searchType].tl} / ${"Open link".tl}',
|
||||||
|
@@ -12,6 +12,14 @@ extension FSExt on FileSystemEntity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> deleteIgnoreError() async {
|
||||||
|
try {
|
||||||
|
await delete();
|
||||||
|
} catch (e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int get size {
|
int get size {
|
||||||
if (this is File) {
|
if (this is File) {
|
||||||
return (this as File).lengthSync();
|
return (this as File).lengthSync();
|
||||||
|
@@ -8,8 +8,14 @@ import 'package:url_launcher/url_launcher_string.dart';
|
|||||||
Future<String> getLatestVersion() async {
|
Future<String> getLatestVersion() async {
|
||||||
var dio = AppDio();
|
var dio = AppDio();
|
||||||
var res = await dio
|
var res = await dio
|
||||||
.get("https://api.github.com/repos/wgh136/pixes/releases/latest");
|
.get("https://raw.githubusercontent.com/wgh136/pixes/refs/heads/master/pubspec.yaml");
|
||||||
return (res.data["tag_name"] as String).replaceFirst("v", "");
|
var lines = (res.data as String).split("\n");
|
||||||
|
for (var line in lines) {
|
||||||
|
if (line.startsWith("version:")) {
|
||||||
|
return line.split(":")[1].split('+')[0].trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw "Failed to get latest version";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compare two versions.
|
/// Compare two versions.
|
||||||
|
27
pubspec.lock
27
pubspec.lock
@@ -256,6 +256,15 @@ packages:
|
|||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
flutter_to_arch:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
path: "."
|
||||||
|
ref: HEAD
|
||||||
|
resolved-ref: b7378b7bda0b71cbc7d103f5afa24bce19be145c
|
||||||
|
url: "https://github.com/wgh136/flutter_to_arch"
|
||||||
|
source: git
|
||||||
|
version: "1.0.0"
|
||||||
flutter_web_plugins:
|
flutter_web_plugins:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
@@ -302,6 +311,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.19.0"
|
version: "0.19.0"
|
||||||
|
io:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: io
|
||||||
|
sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.4"
|
||||||
leak_tracker:
|
leak_tracker:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -740,6 +757,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.4"
|
version: "1.0.4"
|
||||||
|
yaml:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: yaml
|
||||||
|
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.2"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.3.4 <4.0.0"
|
dart: ">=3.3.4 <4.0.0"
|
||||||
flutter: ">=3.19.0"
|
flutter: ">=3.22.3"
|
||||||
|
16
pubspec.yaml
16
pubspec.yaml
@@ -16,10 +16,11 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
|||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
# In Windows, build-name is used as the major, minor, and patch parts
|
# In Windows, build-name is used as the major, minor, and patch parts
|
||||||
# of the product and file versions while build-number is used as the build suffix.
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
version: 1.0.8+108
|
version: 1.0.9+109
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=3.3.4 <4.0.0'
|
sdk: '>=3.3.4 <4.0.0'
|
||||||
|
flutter: 3.22.3
|
||||||
|
|
||||||
# Dependencies specify other packages that your package needs in order to work.
|
# Dependencies specify other packages that your package needs in order to work.
|
||||||
# To automatically upgrade your package dependencies to the latest versions
|
# To automatically upgrade your package dependencies to the latest versions
|
||||||
@@ -72,10 +73,23 @@ dev_dependencies:
|
|||||||
# package. See that file for information about deactivating specific lint
|
# package. See that file for information about deactivating specific lint
|
||||||
# rules and activating additional ones.
|
# rules and activating additional ones.
|
||||||
flutter_lints: ^3.0.0
|
flutter_lints: ^3.0.0
|
||||||
|
flutter_to_arch:
|
||||||
|
git:
|
||||||
|
url: https://github.com/wgh136/flutter_to_arch
|
||||||
|
ref: 15bfead
|
||||||
|
|
||||||
# For information on the generic Dart part of this file, see the
|
# For information on the generic Dart part of this file, see the
|
||||||
# following page: https://dart.dev/tools/pub/pubspec
|
# following page: https://dart.dev/tools/pub/pubspec
|
||||||
|
|
||||||
|
flutter_to_arch:
|
||||||
|
name: Pixes
|
||||||
|
icon: debian/gui/pixes.png
|
||||||
|
categories: Utility
|
||||||
|
keywords: Flutter;pixiv;images;
|
||||||
|
url: https://github.com/wgh136/pixes
|
||||||
|
depends:
|
||||||
|
- gtk3
|
||||||
|
|
||||||
# The following section is specific to Flutter packages.
|
# The following section is specific to Flutter packages.
|
||||||
flutter:
|
flutter:
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user