Skip to content
Merged
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
Binary file added assets/demo/WormholeDemo.pdf
Binary file not shown.
74 changes: 74 additions & 0 deletions lib/transfer/demo_transfer.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/services.dart';
import '../src/rust/wormhole/types/t_update.dart';
import '../src/rust/wormhole/types/events.dart';
import '../src/rust/wormhole/types/value.dart';

/// Generates a demo receive stream that simulates downloading a file
/// without actually connecting to a wormhole server.
/// This is used for App Store review demonstrations.
Stream<TUpdate> generateDemoReceiveStream(String downloadPath) async* {
// Step 1: Connecting
yield const TUpdate(
event: Events.connecting,
value: Value.int(0),
);
await Future.delayed(const Duration(milliseconds: 800));

// Step 2: Start transfer
yield const TUpdate(
event: Events.startTransfer,
value: Value.int(0),
);
await Future.delayed(const Duration(milliseconds: 500));

// Step 3: Send total size (1MB demo file)
const int totalBytes = 1048576; // 1 MB
yield const TUpdate(
event: Events.total,
value: Value.int(totalBytes),
);
await Future.delayed(const Duration(milliseconds: 200));

// Step 4: Simulate progress in chunks
const int chunkSize = 131072; // 128 KB chunks
for (int sent = chunkSize; sent <= totalBytes; sent += chunkSize) {
final int bytesToSend = sent > totalBytes ? totalBytes : sent;
yield TUpdate(
event: Events.sent,
value: Value.int(bytesToSend),
);
await Future.delayed(const Duration(milliseconds: 100));
}

// Step 5: Copy demo file from assets to download path
// Load the demo file from assets
final ByteData data = await rootBundle.load('assets/demo/WormholeDemo.pdf');
final List<int> bytes = data.buffer.asUint8List();

// Create the destination file path
final String fileName = 'WormholeDemo.pdf';
String destinationPath = '$downloadPath${Platform.pathSeparator}$fileName';

// Handle file name conflicts (add number suffix if file exists)
int counter = 1;
while (File(destinationPath).existsSync()) {
destinationPath =
'$downloadPath${Platform.pathSeparator}WormholeDemo ($counter).pdf';
counter++;
}

// Write the file
final File file = File(destinationPath);
await file.writeAsBytes(bytes);
final finalPath = destinationPath;

await Future.delayed(const Duration(milliseconds: 300));

// Step 6: Finished
yield TUpdate(
event: Events.finished,
value: Value.string(finalPath),
);
}
17 changes: 17 additions & 0 deletions lib/transfer/transfer_receiver.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ import '../pages/transfer_widgets/transfer_finished.dart';
import '../settings/settings.dart';
import '../utils/paths.dart';
import '../utils/logger.dart';
import '../utils/code.dart';
import 'transfer_provider.dart';
import 'demo_transfer.dart';

class TransferReceiver extends StatefulWidget {
const TransferReceiver({super.key, required this.child});
Expand Down Expand Up @@ -111,6 +113,21 @@ class _TransferReceiverState extends State<TransferReceiver> {
return;
}

// Check if this is a demo code for App Store review
if (isDemoCode(passphrase)) {
// Use demo transfer stream instead of real wormhole connection
final s = generateDemoReceiveStream(dpath);
if (!mounted) return;
Provider.of<NavigationProvider>(context, listen: false).push(
ConnectingPage(
key: UniqueKey(),
stream: s,
finish: (file) => ReceiveFinished(file: file),
),
);
return;
}

// we need storage permission to store files
if (!(Platform.isAndroid || Platform.isIOS) ||
(Platform.isAndroid &&
Expand Down
9 changes: 9 additions & 0 deletions lib/utils/code.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
// regex to match code validity
final RegExp _regex = RegExp(r'^\d+-[^\s]*$');

/// Demo code for App Store review (simulates file transfer without server)
const String demoCode =
'999763-demoooooo-mode-transfer-that-should-never-collide';

/// Check if the provided code is the demo code
bool isDemoCode(String code) {
return code == demoCode;
}

/// validate syntax of correction code
bool isCodeValid(String code) {
return _regex.hasMatch(code);
Expand Down
4 changes: 4 additions & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ flutter:
# include material icons
uses-material-design: true

# include demo assets for App Store review
assets:
- assets/demo/

# app icon generation
flutter_launcher_icons:
android: "ic_launcher"
Expand Down
Loading