mirror of
https://github.com/venera-app/venera.git
synced 2025-09-27 15:57:25 +00:00
Reduce app size
This commit is contained in:
@@ -3,7 +3,6 @@ import 'package:desktop_webview_window/desktop_webview_window.dart';
|
|||||||
import 'package:dynamic_color/dynamic_color.dart';
|
import 'package:dynamic_color/dynamic_color.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
|
||||||
import 'package:rhttp/rhttp.dart';
|
import 'package:rhttp/rhttp.dart';
|
||||||
import 'package:venera/foundation/log.dart';
|
import 'package:venera/foundation/log.dart';
|
||||||
import 'package:venera/pages/auth_page.dart';
|
import 'package:venera/pages/auth_page.dart';
|
||||||
@@ -197,11 +196,6 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
|
|||||||
'dark' => ThemeMode.dark,
|
'dark' => ThemeMode.dark,
|
||||||
_ => ThemeMode.system
|
_ => ThemeMode.system
|
||||||
},
|
},
|
||||||
localizationsDelegates: const [
|
|
||||||
GlobalMaterialLocalizations.delegate,
|
|
||||||
GlobalWidgetsLocalizations.delegate,
|
|
||||||
GlobalCupertinoLocalizations.delegate,
|
|
||||||
],
|
|
||||||
locale: () {
|
locale: () {
|
||||||
var lang = appdata.settings['language'];
|
var lang = appdata.settings['language'];
|
||||||
if (lang == 'system') {
|
if (lang == 'system') {
|
||||||
|
@@ -26,7 +26,7 @@ class Image {
|
|||||||
var codec = await ui.instantiateImageCodec(data);
|
var codec = await ui.instantiateImageCodec(data);
|
||||||
var frame = await codec.getNextFrame();
|
var frame = await codec.getNextFrame();
|
||||||
codec.dispose();
|
codec.dispose();
|
||||||
var info = await frame.image.toByteData();
|
var info = await frame.image.toByteData(format: ui.ImageByteFormat.rawStraightRgba);
|
||||||
if (info == null) {
|
if (info == null) {
|
||||||
throw Exception('Failed to decode image');
|
throw Exception('Failed to decode image');
|
||||||
}
|
}
|
||||||
@@ -39,6 +39,14 @@ class Image {
|
|||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getPixelAtIndex(int index) {
|
||||||
|
if (index < 0 || index >= _data.length) {
|
||||||
|
throw ArgumentError(
|
||||||
|
'Invalid argument: index must be in the range of [0, ${_data.length}).');
|
||||||
|
}
|
||||||
|
return _data[index];
|
||||||
|
}
|
||||||
|
|
||||||
Image copyRange(int x, int y, int width, int height) {
|
Image copyRange(int x, int y, int width, int height) {
|
||||||
if (width + x > this.width) {
|
if (width + x > this.width) {
|
||||||
throw ArgumentError('''
|
throw ArgumentError('''
|
||||||
|
@@ -1,33 +1,28 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
import 'dart:isolate';
|
import 'dart:isolate';
|
||||||
|
import 'package:venera/foundation/app.dart';
|
||||||
import 'package:pdf/widgets.dart';
|
|
||||||
import 'package:venera/foundation/local.dart';
|
import 'package:venera/foundation/local.dart';
|
||||||
|
import 'package:venera/utils/image.dart';
|
||||||
import 'package:venera/utils/io.dart';
|
import 'package:venera/utils/io.dart';
|
||||||
|
import 'package:zip_flutter/zip_flutter.dart';
|
||||||
|
|
||||||
|
typedef DecodeImage = Future<Image> Function(Uint8List data);
|
||||||
|
|
||||||
Future<void> _createPdfFromComic({
|
Future<void> _createPdfFromComic({
|
||||||
required LocalComic comic,
|
required LocalComic comic,
|
||||||
required String savePath,
|
required String savePath,
|
||||||
required String localPath,
|
required String localPath,
|
||||||
|
required DecodeImage decodeImage,
|
||||||
}) async {
|
}) async {
|
||||||
final pdf = Document(
|
var images = <String>[];
|
||||||
title: comic.title,
|
|
||||||
author: comic.subTitle ?? "",
|
|
||||||
producer: "Venera",
|
|
||||||
);
|
|
||||||
|
|
||||||
pdf.document.outline;
|
|
||||||
|
|
||||||
var baseDir = comic.directory.contains('/') || comic.directory.contains('\\')
|
var baseDir = comic.directory.contains('/') || comic.directory.contains('\\')
|
||||||
? comic.directory
|
? comic.directory
|
||||||
: FilePath.join(localPath, comic.directory);
|
: FilePath.join(localPath, comic.directory);
|
||||||
|
|
||||||
// add cover
|
// add cover
|
||||||
var imageData = File(FilePath.join(baseDir, comic.cover)).readAsBytesSync();
|
images.add(FilePath.join(baseDir, comic.cover));
|
||||||
pdf.addPage(Page(
|
|
||||||
build: (Context context) {
|
|
||||||
return Image(MemoryImage(imageData), fit: BoxFit.contain);
|
|
||||||
},
|
|
||||||
));
|
|
||||||
|
|
||||||
bool multiChapters = comic.chapters != null;
|
bool multiChapters = comic.chapters != null;
|
||||||
|
|
||||||
@@ -51,42 +46,360 @@ Future<void> _createPdfFromComic({
|
|||||||
reorderFiles(files);
|
reorderFiles(files);
|
||||||
|
|
||||||
for (var file in files) {
|
for (var file in files) {
|
||||||
var imageData = (file as File).readAsBytesSync();
|
images.add(file.path);
|
||||||
pdf.addPage(Page(
|
|
||||||
build: (Context context) {
|
|
||||||
return Image(MemoryImage(imageData), fit: BoxFit.contain);
|
|
||||||
},
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (var chapter in comic.chapters!.keys) {
|
for (var chapter in comic.chapters!.keys) {
|
||||||
var files = Directory(FilePath.join(baseDir, chapter)).listSync();
|
var files = Directory(FilePath.join(baseDir, chapter)).listSync();
|
||||||
reorderFiles(files);
|
reorderFiles(files);
|
||||||
for (var file in files) {
|
for (var file in files) {
|
||||||
var imageData = (file as File).readAsBytesSync();
|
images.add(file.path);
|
||||||
pdf.addPage(Page(
|
|
||||||
build: (Context context) {
|
|
||||||
return Image(MemoryImage(imageData), fit: BoxFit.contain);
|
|
||||||
},
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final file = File(savePath);
|
var generator = PdfGenerator(
|
||||||
file.writeAsBytesSync(await pdf.save());
|
title: comic.title,
|
||||||
|
author: comic.subtitle,
|
||||||
|
imagePaths: images,
|
||||||
|
outputPath: savePath,
|
||||||
|
decodeImage: decodeImage,
|
||||||
|
);
|
||||||
|
await generator.generate();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Isolate> _runIsolate(
|
||||||
|
LocalComic comic, String savePath, SendPort sendPort) {
|
||||||
|
var localPath = LocalManager().path;
|
||||||
|
return Isolate.spawn<SendPort>(
|
||||||
|
(sendPort) => overrideIO(
|
||||||
|
() async {
|
||||||
|
var receivePort = ReceivePort();
|
||||||
|
sendPort.send(receivePort.sendPort);
|
||||||
|
|
||||||
|
Completer<Image>? completer;
|
||||||
|
|
||||||
|
Future<Image> decodeImage(Uint8List data) async {
|
||||||
|
if (completer != null) {
|
||||||
|
throw Exception('Another image is being decoded');
|
||||||
|
}
|
||||||
|
sendPort.send(data);
|
||||||
|
completer = Completer();
|
||||||
|
return completer!.future;
|
||||||
|
}
|
||||||
|
|
||||||
|
receivePort.listen((message) {
|
||||||
|
if (message is Image) {
|
||||||
|
if (completer == null) {
|
||||||
|
throw Exception('No image is being decoded');
|
||||||
|
}
|
||||||
|
completer!.complete(message);
|
||||||
|
completer = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await _createPdfFromComic(
|
||||||
|
comic: comic,
|
||||||
|
savePath: savePath,
|
||||||
|
localPath: localPath,
|
||||||
|
decodeImage: decodeImage,
|
||||||
|
);
|
||||||
|
|
||||||
|
sendPort.send(null);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
sendPort,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> createPdfFromComicIsolate({
|
Future<void> createPdfFromComicIsolate({
|
||||||
required LocalComic comic,
|
required LocalComic comic,
|
||||||
required String savePath,
|
required String savePath,
|
||||||
}) async {
|
}) async {
|
||||||
var localPath = LocalManager().path;
|
var receivePort = ReceivePort();
|
||||||
return Isolate.run(() => overrideIO(() async {
|
SendPort? sendPort;
|
||||||
return await _createPdfFromComic(
|
Isolate? isolate;
|
||||||
comic: comic,
|
var completer = Completer<void>();
|
||||||
savePath: savePath,
|
receivePort.listen((message) {
|
||||||
localPath: localPath,
|
if (message is SendPort) {
|
||||||
);
|
sendPort = message;
|
||||||
}));
|
} else if (message is Uint8List) {
|
||||||
|
Image.decodeImage(message).then((image) {
|
||||||
|
sendPort!.send(image);
|
||||||
|
});
|
||||||
|
} else if (message == null) {
|
||||||
|
receivePort.close();
|
||||||
|
completer.complete();
|
||||||
|
isolate!.kill();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
isolate = await _runIsolate(comic, savePath, receivePort.sendPort);
|
||||||
|
return completer.future;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PdfGenerator {
|
||||||
|
final String title;
|
||||||
|
final String author;
|
||||||
|
final List<String> imagePaths;
|
||||||
|
final String outputPath;
|
||||||
|
final DecodeImage decodeImage;
|
||||||
|
|
||||||
|
// PDF文件的对象ID计数器
|
||||||
|
int _objectId = 1;
|
||||||
|
|
||||||
|
// 存储每个对象在PDF中的字节位置
|
||||||
|
final Map<int, int> _objectOffsets = {};
|
||||||
|
|
||||||
|
static const double a4Width = 595.0; // points
|
||||||
|
static const double a4Height = 842.0; // points
|
||||||
|
|
||||||
|
PdfGenerator({
|
||||||
|
required this.title,
|
||||||
|
required this.author,
|
||||||
|
required this.imagePaths,
|
||||||
|
required this.outputPath,
|
||||||
|
required this.decodeImage,
|
||||||
|
});
|
||||||
|
|
||||||
|
Future<void> generate() async {
|
||||||
|
var file = File(outputPath);
|
||||||
|
final output = file.openWrite();
|
||||||
|
|
||||||
|
int length = 0;
|
||||||
|
|
||||||
|
void write(String str) {
|
||||||
|
var data = utf8.encode(str);
|
||||||
|
output.add(data);
|
||||||
|
length += data.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeData(Uint8List data) {
|
||||||
|
output.add(data);
|
||||||
|
length += data.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getCurrentLength() {
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 写入PDF头部
|
||||||
|
write('%PDF-1.7\n%\xFF\xFF\xFF\xFF\n\n');
|
||||||
|
|
||||||
|
// 2. 写入Catalog对象
|
||||||
|
_objectOffsets[_objectId] = getCurrentLength();
|
||||||
|
write('$_objectId 0 obj\n');
|
||||||
|
write('<<\n');
|
||||||
|
write('/Type /Catalog\n');
|
||||||
|
write('/Pages ${_objectId + 1} 0 R\n');
|
||||||
|
write('>>\nendobj\n\n');
|
||||||
|
|
||||||
|
final catalogId = _objectId++;
|
||||||
|
|
||||||
|
// 3. 写入Pages对象
|
||||||
|
_objectOffsets[_objectId] = getCurrentLength();
|
||||||
|
write('$_objectId 0 obj\n');
|
||||||
|
write('<<\n');
|
||||||
|
write('/Type /Pages\n');
|
||||||
|
write('/Kids [');
|
||||||
|
final pageIds = <int>[];
|
||||||
|
for (var i = 0; i < imagePaths.length; i++) {
|
||||||
|
pageIds.add(_objectId + 1 + i * 3);
|
||||||
|
write('${_objectId + 1 + i * 3} 0 R ');
|
||||||
|
}
|
||||||
|
write(']\n');
|
||||||
|
write('/Count ${imagePaths.length}\n');
|
||||||
|
write('>>\nendobj\n\n');
|
||||||
|
|
||||||
|
final pagesId = _objectId++;
|
||||||
|
|
||||||
|
// 4. 为每个图片创建Page和Image对象
|
||||||
|
for (var i = 0; i < imagePaths.length; i++) {
|
||||||
|
final imagePath = imagePaths[i];
|
||||||
|
final image = await _getImage(imagePath);
|
||||||
|
|
||||||
|
// 写入Page对象
|
||||||
|
_objectOffsets[_objectId] = getCurrentLength();
|
||||||
|
write('$_objectId 0 obj\n');
|
||||||
|
write('<<\n');
|
||||||
|
write('/Type /Page\n');
|
||||||
|
write('/Parent $pagesId 0 R\n');
|
||||||
|
write('/Resources <<\n');
|
||||||
|
write('/XObject << /Im${i + 1} ${_objectId + 1} 0 R >>\n');
|
||||||
|
write('>>\n');
|
||||||
|
write('/MediaBox [0 0 $a4Width $a4Height]\n');
|
||||||
|
write('/Contents ${_objectId + 2} 0 R\n');
|
||||||
|
write('>>\nendobj\n\n');
|
||||||
|
|
||||||
|
_objectId++;
|
||||||
|
|
||||||
|
// 写入Image对象
|
||||||
|
_objectOffsets[_objectId] = getCurrentLength();
|
||||||
|
write('$_objectId 0 obj\n');
|
||||||
|
write('<<\n');
|
||||||
|
write('/Type /XObject\n');
|
||||||
|
write('/Subtype /Image\n');
|
||||||
|
write('/Width ${image.width}\n');
|
||||||
|
write('/Height ${image.height}\n');
|
||||||
|
write('/ColorSpace /DeviceRGB\n');
|
||||||
|
write('/BitsPerComponent 8\n');
|
||||||
|
write('/Filter /FlateDecode\n');
|
||||||
|
write('/Length ${image.data.length}\n');
|
||||||
|
write('>>\nstream\n');
|
||||||
|
writeData(image.data);
|
||||||
|
write('\nendstream\nendobj\n\n');
|
||||||
|
|
||||||
|
_objectId++;
|
||||||
|
|
||||||
|
// 写入Contents对象(绘制图片的指令)
|
||||||
|
_objectOffsets[_objectId] = getCurrentLength();
|
||||||
|
write('$_objectId 0 obj\n');
|
||||||
|
write('<<\n');
|
||||||
|
var stream = '';
|
||||||
|
stream += 'q\n';
|
||||||
|
// Calculate scaling factors
|
||||||
|
var scaleX = a4Width / image.width;
|
||||||
|
var scaleY = a4Height / image.height;
|
||||||
|
var scale = scaleX < scaleY ? scaleX : scaleY;
|
||||||
|
// Calculate centering offsets
|
||||||
|
var offsetX = (a4Width - (image.width * scale)) / 2;
|
||||||
|
var offsetY = (a4Height - (image.height * scale)) / 2;
|
||||||
|
// Apply transformation matrix
|
||||||
|
stream += '1 0 0 1 $offsetX $offsetY cm\n'; // Translate
|
||||||
|
stream += '${scale * image.width} 0 0 ${scale * image.height} 0 0 cm\n';
|
||||||
|
stream += '/Im${i + 1} Do\n';
|
||||||
|
stream += 'Q\n';
|
||||||
|
var streamData = utf8.encode(stream);
|
||||||
|
write('/Length ${streamData.length}\n');
|
||||||
|
write('>>\nstream\n');
|
||||||
|
writeData(streamData);
|
||||||
|
write('endstream\nendobj\n\n');
|
||||||
|
|
||||||
|
_objectId++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 写入Info对象(元数据)
|
||||||
|
final infoId = _objectId;
|
||||||
|
_objectOffsets[_objectId] = getCurrentLength();
|
||||||
|
write('$_objectId 0 obj\n');
|
||||||
|
write('<<\n');
|
||||||
|
write('/Title <');
|
||||||
|
writeData(_toPdfString(title));
|
||||||
|
write('>\n');
|
||||||
|
write('/Author <');
|
||||||
|
writeData(_toPdfString(author));
|
||||||
|
write('>\n');
|
||||||
|
write('/Producer (venera v${App.version})\n');
|
||||||
|
write('/CreationDate (D:${_formatDateTime(DateTime.now())})\n');
|
||||||
|
write('>>\nendobj\n\n');
|
||||||
|
|
||||||
|
_objectId++;
|
||||||
|
|
||||||
|
// 6. 写入交叉引用表
|
||||||
|
final xrefOffset = getCurrentLength();
|
||||||
|
write('xref\n');
|
||||||
|
write('0 $_objectId\n');
|
||||||
|
write('0000000000 65535 f\r\n');
|
||||||
|
|
||||||
|
for (var i = 1; i < _objectId; i++) {
|
||||||
|
final offset = _objectOffsets[i]!;
|
||||||
|
write('${offset.toString().padLeft(10, '0')} 00000 n\r\n'); // 使用\r\n
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7. 写入文件尾部
|
||||||
|
write('trailer\n');
|
||||||
|
write('<<\n');
|
||||||
|
write('/Size $_objectId\n');
|
||||||
|
write('/Root $catalogId 0 R\n');
|
||||||
|
write('/Info $infoId 0 R\n');
|
||||||
|
write('>>\n');
|
||||||
|
write('startxref\n');
|
||||||
|
write('$xrefOffset\n');
|
||||||
|
write('%%EOF\n');
|
||||||
|
|
||||||
|
await output.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
int _codeUnitForDigit(int digit) =>
|
||||||
|
digit < 10 ? digit + 0x30 : digit + 0x61 - 10;
|
||||||
|
|
||||||
|
Uint8List _toPdfString(String str) {
|
||||||
|
Uint8List data;
|
||||||
|
try {
|
||||||
|
data = latin1.encode(str);
|
||||||
|
} catch (e) {
|
||||||
|
data = Uint8List.fromList(<int>[0xfe, 0xff] + _encodeUtf16be(str));
|
||||||
|
}
|
||||||
|
var result = <int>[];
|
||||||
|
for (final byte in data) {
|
||||||
|
result.add(_codeUnitForDigit((byte & 0xF0) >> 4));
|
||||||
|
result.add(_codeUnitForDigit(byte & 0x0F));
|
||||||
|
}
|
||||||
|
return Uint8List.fromList(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<int> _encodeUtf16be(String str) {
|
||||||
|
const unicodeReplacementCharacterCodePoint = 0xfffd;
|
||||||
|
const unicodeByteZeroMask = 0xff;
|
||||||
|
const unicodeByteOneMask = 0xff00;
|
||||||
|
const unicodeValidRangeMax = 0x10ffff;
|
||||||
|
const unicodePlaneOneMax = 0xffff;
|
||||||
|
const unicodeUtf16ReservedLo = 0xd800;
|
||||||
|
const unicodeUtf16ReservedHi = 0xdfff;
|
||||||
|
const unicodeUtf16Offset = 0x10000;
|
||||||
|
const unicodeUtf16SurrogateUnit0Base = 0xd800;
|
||||||
|
const unicodeUtf16SurrogateUnit1Base = 0xdc00;
|
||||||
|
const unicodeUtf16HiMask = 0xffc00;
|
||||||
|
const unicodeUtf16LoMask = 0x3ff;
|
||||||
|
|
||||||
|
final encoding = <int>[];
|
||||||
|
|
||||||
|
void add(int unit) {
|
||||||
|
encoding.add((unit & unicodeByteOneMask) >> 8);
|
||||||
|
encoding.add(unit & unicodeByteZeroMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final unit in str.codeUnits) {
|
||||||
|
if ((unit >= 0 && unit < unicodeUtf16ReservedLo) ||
|
||||||
|
(unit > unicodeUtf16ReservedHi && unit <= unicodePlaneOneMax)) {
|
||||||
|
add(unit);
|
||||||
|
} else if (unit > unicodePlaneOneMax && unit <= unicodeValidRangeMax) {
|
||||||
|
final base = unit - unicodeUtf16Offset;
|
||||||
|
add(unicodeUtf16SurrogateUnit0Base +
|
||||||
|
((base & unicodeUtf16HiMask) >> 10));
|
||||||
|
add(unicodeUtf16SurrogateUnit1Base + (base & unicodeUtf16LoMask));
|
||||||
|
} else {
|
||||||
|
add(unicodeReplacementCharacterCodePoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return encoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化日期时间
|
||||||
|
String _formatDateTime(DateTime dt) {
|
||||||
|
return dt
|
||||||
|
.toUtc()
|
||||||
|
.toString()
|
||||||
|
.replaceAll('-', '')
|
||||||
|
.replaceAll(':', '')
|
||||||
|
.replaceAll(' ', '')
|
||||||
|
.replaceAll('.', '')
|
||||||
|
.substring(0, 14);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<({int width, int height, Uint8List data})> _getImage(
|
||||||
|
String imagePath) async {
|
||||||
|
var data = await File(imagePath).readAsBytes();
|
||||||
|
var image = await decodeImage(data);
|
||||||
|
var width = image.width;
|
||||||
|
var height = image.height;
|
||||||
|
data = Uint8List(width * height * 3);
|
||||||
|
for (var i = 0; i < width * height; i++) {
|
||||||
|
var pixel = image.getPixelAtIndex(i); // RGBA
|
||||||
|
data[i * 3] = pixel & 0xFF; // R
|
||||||
|
data[i * 3 + 1] = (pixel >> 8) & 0xFF; // G
|
||||||
|
data[i * 3 + 2] = (pixel >> 16) & 0xFF; // B
|
||||||
|
}
|
||||||
|
data = tdeflCompressData(data, true, true, 9);
|
||||||
|
return (width: width, height: height, data: data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
67
pubspec.lock
67
pubspec.lock
@@ -33,14 +33,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.4"
|
version: "1.0.4"
|
||||||
archive:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: archive
|
|
||||||
sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.6.1"
|
|
||||||
args:
|
args:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -57,14 +49,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.11.0"
|
version: "2.11.0"
|
||||||
barcode:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: barcode
|
|
||||||
sha256: ab180ce22c6555d77d45f0178a523669db67f95856e3378259ef2ffeb43e6003
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.2.8"
|
|
||||||
battery_plus:
|
battery_plus:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -81,14 +65,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.1"
|
version: "2.0.1"
|
||||||
bidi:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: bidi
|
|
||||||
sha256: "9a712c7ddf708f7c41b1923aa83648a3ed44cfd75b04f72d598c45e5be287f9d"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.0.12"
|
|
||||||
boolean_selector:
|
boolean_selector:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -392,11 +368,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.0.0"
|
version: "5.0.0"
|
||||||
flutter_localizations:
|
|
||||||
dependency: "direct main"
|
|
||||||
description: flutter
|
|
||||||
source: sdk
|
|
||||||
version: "0.0.0"
|
|
||||||
flutter_memory_info:
|
flutter_memory_info:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -521,14 +492,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.0"
|
version: "0.1.0"
|
||||||
image:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: image
|
|
||||||
sha256: f31d52537dc417fdcde36088fdf11d191026fd5e4fae742491ebd40e5a8bea7d
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "4.3.0"
|
|
||||||
intl:
|
intl:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -690,14 +653,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.9.0"
|
version: "1.9.0"
|
||||||
path_parsing:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: path_parsing
|
|
||||||
sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.1.0"
|
|
||||||
path_provider:
|
path_provider:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -746,14 +701,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.0"
|
version: "2.3.0"
|
||||||
pdf:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: pdf
|
|
||||||
sha256: "05df53f8791587402493ac97b9869d3824eccbc77d97855f4545cf72df3cae07"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.11.1"
|
|
||||||
petitparser:
|
petitparser:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -795,14 +742,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.9.1"
|
version: "3.9.1"
|
||||||
qr:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: qr
|
|
||||||
sha256: "5a1d2586170e172b8a8c8470bbbffd5eb0cd38a66c0d77155ea138d3af3a4445"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.0.2"
|
|
||||||
rhttp:
|
rhttp:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -1131,7 +1070,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "6.5.0"
|
version: "6.5.0"
|
||||||
yaml:
|
yaml:
|
||||||
dependency: "direct main"
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: yaml
|
name: yaml
|
||||||
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
|
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
|
||||||
@@ -1142,10 +1081,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: zip_flutter
|
name: zip_flutter
|
||||||
sha256: ea7fdc86c988174ef3bb80dc26e8e8bfdf634c55930e2d18d7e77e991acf0483
|
sha256: fe63ef9098bb2426b001adba2e28029820d71ce80cce957a36676bd6b3227245
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.0.8"
|
version: "0.0.9"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.6.0 <4.0.0"
|
dart: ">=3.6.0 <4.0.0"
|
||||||
flutter: ">=3.27.2"
|
flutter: ">=3.27.2"
|
||||||
|
@@ -12,8 +12,6 @@ dependencies:
|
|||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
path_provider: any
|
path_provider: any
|
||||||
flutter_localizations:
|
|
||||||
sdk: flutter
|
|
||||||
intl: ^0.19.0
|
intl: ^0.19.0
|
||||||
window_manager: ^0.4.3
|
window_manager: ^0.4.3
|
||||||
sqlite3: ^2.4.7
|
sqlite3: ^2.4.7
|
||||||
@@ -25,7 +23,7 @@ dependencies:
|
|||||||
crypto: ^3.0.6
|
crypto: ^3.0.6
|
||||||
dio: ^5.7.0
|
dio: ^5.7.0
|
||||||
html: ^0.15.5
|
html: ^0.15.5
|
||||||
pointycastle: any
|
pointycastle: ^3.9.1
|
||||||
url_launcher: ^6.3.0
|
url_launcher: ^6.3.0
|
||||||
path: ^1.9.0
|
path: ^1.9.0
|
||||||
photo_view:
|
photo_view:
|
||||||
@@ -40,7 +38,6 @@ dependencies:
|
|||||||
ref: 09e756b1f1b04e6298318d99ec20a787fb360f59
|
ref: 09e756b1f1b04e6298318d99ec20a787fb360f59
|
||||||
path: packages/scrollable_positioned_list
|
path: packages/scrollable_positioned_list
|
||||||
flutter_reorderable_grid_view: ^5.4.0
|
flutter_reorderable_grid_view: ^5.4.0
|
||||||
yaml: any
|
|
||||||
uuid: ^4.5.1
|
uuid: ^4.5.1
|
||||||
desktop_webview_window:
|
desktop_webview_window:
|
||||||
git:
|
git:
|
||||||
@@ -51,7 +48,7 @@ dependencies:
|
|||||||
sliver_tools: ^0.2.12
|
sliver_tools: ^0.2.12
|
||||||
flutter_file_dialog: ^3.0.2
|
flutter_file_dialog: ^3.0.2
|
||||||
file_selector: ^1.0.3
|
file_selector: ^1.0.3
|
||||||
zip_flutter: ^0.0.8
|
zip_flutter: ^0.0.9
|
||||||
lodepng_flutter:
|
lodepng_flutter:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/venera-app/lodepng_flutter
|
url: https://github.com/venera-app/lodepng_flutter
|
||||||
@@ -67,7 +64,6 @@ dependencies:
|
|||||||
git:
|
git:
|
||||||
url: https://github.com/pkuislm/flutter_saf.git
|
url: https://github.com/pkuislm/flutter_saf.git
|
||||||
ref: 7637b8b67d0a831f3cd7e702b8173e300880d32e
|
ref: 7637b8b67d0a831f3cd7e702b8173e300880d32e
|
||||||
pdf: ^3.11.1
|
|
||||||
dynamic_color: ^1.7.0
|
dynamic_color: ^1.7.0
|
||||||
shimmer_animation: ^2.1.0
|
shimmer_animation: ^2.1.0
|
||||||
flutter_memory_info: ^0.0.1
|
flutter_memory_info: ^0.0.1
|
||||||
|
Reference in New Issue
Block a user