Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions example/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:label="pdf_combiner_example"
android:name="${applicationName}"
Expand Down
44 changes: 0 additions & 44 deletions example/ios/Podfile

This file was deleted.

14 changes: 8 additions & 6 deletions example/ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 60;
objectVersion = 54;
objects = {

/* Begin PBXBuildFile section */
Expand Down Expand Up @@ -48,6 +48,7 @@
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
Expand Down Expand Up @@ -88,6 +89,7 @@
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */,
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
Expand Down Expand Up @@ -204,7 +206,7 @@
);
mainGroup = 97C146E51CF9000F007C117D;
packageReferences = (
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */,
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */,
);
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
projectDirPath = "";
Expand Down Expand Up @@ -362,7 +364,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
Expand Down Expand Up @@ -495,7 +497,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
Expand Down Expand Up @@ -546,7 +548,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
Expand Down Expand Up @@ -644,7 +646,7 @@
/* End XCConfigurationList section */

/* Begin XCLocalSwiftPackageReference section */
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = {
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = {
isa = XCLocalSwiftPackageReference;
relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage;
};
Expand Down
5 changes: 5 additions & 0 deletions example/ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,10 @@
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
</dict>
</plist>
42 changes: 42 additions & 0 deletions example/lib/view_models/pdf_combiner_view_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'dart:io';
import 'package:desktop_drop/desktop_drop.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http;
import 'package:path_provider/path_provider.dart';
import 'package:pdf_combiner/exception/pdf_combiner_exception.dart';
import 'package:pdf_combiner/models/merge_input.dart';
Expand Down Expand Up @@ -31,6 +32,9 @@ class PdfCombinerViewModel {
selectedFiles +=
result.files.map((file) => MergeInput.bytes(file.bytes!)).toList();
break;
case MergeInputType.url:
// Currently not supported in file picker
break;
}
}

Expand All @@ -51,6 +55,9 @@ class PdfCombinerViewModel {
),
);
break;
case MergeInputType.url:
// Currently not supported in drag and drop
break;
}

outputFiles = [];
Expand Down Expand Up @@ -155,4 +162,39 @@ class PdfCombinerViewModel {
void removeFileAt(int index) {
selectedFiles.removeAt(index);
}

/// Function to format bytes into a human-readable string
String formatBytes(int bytes) {
if (bytes >= 1e9) return "${(bytes / 1e9).toStringAsFixed(2)} GB";
if (bytes >= 1e6) return "${(bytes / 1e6).toStringAsFixed(2)} MB";
if (bytes >= 1e3) return "${(bytes / 1e3).toStringAsFixed(2)} KB";
return "$bytes B";
}

/// Function to get the file size from a URL
Future<int?> getUrlFileSize(String url) async {
final uri = Uri.parse(url);
final client = http.Client();
try {
final head = await client.head(uri);
if (head.statusCode >= 200 && head.statusCode < 300) {
final cl = head.headers['content-length'];
if (cl != null) return int.tryParse(cl);
}

final range = await client.get(uri, headers: {'Range': 'bytes=0-0'});
if (range.statusCode == 206) {
final cr = range.headers['content-range'];
if (cr != null) {
final parts = cr.split('/');
if (parts.length == 2) return int.tryParse(parts[1]);
}
}
} catch (_) {
return null;
} finally {
client.close();
}
return null;
}
}
53 changes: 44 additions & 9 deletions example/lib/views/pdf_combiner_screen.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:typed_data';

import 'package:desktop_drop/desktop_drop.dart';
import 'package:file_magic_number/file_magic_number.dart';
import 'package:flutter/material.dart';
Expand All @@ -8,7 +10,7 @@ import 'package:pdf_combiner/models/merge_input.dart';
import 'package:pdf_combiner_example/utils/uint8list_extension.dart';
import 'package:pdf_combiner_example/views/widgets/file_type_dialog.dart';
import 'package:pdf_combiner_example/views/widgets/file_type_icon.dart';

import 'package:http/http.dart' as http;
import '../view_models/pdf_combiner_view_model.dart';

extension on MergeInput {
Expand All @@ -18,6 +20,8 @@ extension on MergeInput {
return p.basename(path ?? '');
case MergeInputType.bytes:
return 'File in bytes $index';
case MergeInputType.url:
return url ?? 'File from URL $index';
}
}
}
Expand Down Expand Up @@ -56,10 +60,19 @@ class _PdfCombinerScreenState extends State<PdfCombinerScreen> {
children: [
DropTarget(
onDragDone: (details) async {
final fileType =
await showFileTypeDialog(context); // Show dialog
if (fileType == null) return;
await _viewModel.addFilesDragAndDrop(fileType, details.files);
final selection =
await showFileTypeDialog(context, isDrag: true); // Show dialog
if (selection == null) return;
if (selection.type == MergeInputType.url) {
if (selection.url != null && selection.url!.isNotEmpty) {
_viewModel.selectedFiles += [
MergeInput.url(selection.url!)
];
}
} else {
await _viewModel.addFilesDragAndDrop(
selection.type, details.files);
}
setState(() {});
},
child: (_viewModel.isEmpty())
Expand Down Expand Up @@ -188,6 +201,9 @@ class _PdfCombinerScreenState extends State<PdfCombinerScreen> {
.getBytesFromPathOrBlob(_viewModel
.selectedFiles[index]
.toString()),
MergeInputType.url => _viewModel.getUrlFileSize(
_viewModel.selectedFiles[index]
.toString()),
},
builder: (context, snapshot) {
if (snapshot.connectionState ==
Expand All @@ -197,7 +213,17 @@ class _PdfCombinerScreenState extends State<PdfCombinerScreen> {
} else if (snapshot.hasError) {
return const Icon(Icons.error);
} else {
return Text(snapshot.data?.size() ??
final input =
_viewModel.selectedFiles[index];
if (input.type ==
MergeInputType.url) {
final len = snapshot.data as int?;
return Text(len != null
? _viewModel.formatBytes(len)
: "Unknown Size");
}
final snapshotUint = snapshot.data as Uint8List?;
return Text(snapshotUint?.size() ??
"Unknown Size");
}
}),
Expand Down Expand Up @@ -270,9 +296,16 @@ class _PdfCombinerScreenState extends State<PdfCombinerScreen> {

// Function to pick PDF files from the device
Future<void> _pickFiles() async {
final fileType = await showFileTypeDialog(context);
if (fileType == null) return;
await _viewModel.pickFiles(fileType);
final selection = await showFileTypeDialog(context);
if (selection == null) return;
if (selection.type == MergeInputType.url) {
if (selection.url != null && selection.url!.isNotEmpty) {
_viewModel.selectedFiles += [MergeInput.url(selection.url!)];
}
setState(() {});
} else {
await _viewModel.pickFiles(selection.type);
}
setState(() {});
}

Expand Down Expand Up @@ -353,6 +386,8 @@ class _PdfCombinerScreenState extends State<PdfCombinerScreen> {
return;
case MergeInputType.bytes:
return;
case MergeInputType.url:
return;
}
}
}
Expand Down
Loading